當(dāng)多個(gè)線程共享一個(gè)全局變量,對(duì)其做寫(xiě)操作時(shí),可能會(huì)受到其他線程的干擾,從而引發(fā)線程安全問(wèn)題
內(nèi)置鎖也叫互斥鎖,可以保證線程的原子性,當(dāng)線程進(jìn)入方法時(shí),會(huì)自動(dòng)獲得一個(gè)鎖,一旦鎖被獲得,其他線程必須等待獲得鎖的線程執(zhí)行完代碼釋放鎖,會(huì)降低程序的執(zhí)行效率
使用方式:
同步方法
public synchronized void sale() {
if (trainCount > 0) {
System.out.println(Thread.currentThread().getName() + "票" + (100 - trainCount + 1) + "張票");
trainCount --;
}
}
// 非靜態(tài)同步方法使用this鎖
// 靜態(tài)同步方法使用當(dāng)前字節(jié)碼文件
同步代碼塊
private Object obj = new Object();
....
public void sale() {
// 參數(shù)為任意全局對(duì)象
synchronized (obj) {
if (trainCount > 0) {
System.out.println(Thread.currentThread().getName() + "票" + (100 - trainCount + 1) + "張票");
trainCount --;
}
}
}
注意事項(xiàng):
public static void main(String[] args) {
ThreadDemo1 threadDemo1 = new ThreadDemo1();
ThreadDemo1 threadDemo2 = new ThreadDemo1();
Thread t1 = new Thread(threadDemo1, "窗口1");
Thread t2 = new Thread(threadDemo2, "窗口2");
t1.start();
t2.start();
}
// 這樣的話也會(huì)產(chǎn)生線程安全問(wèn)題
// 那是因?yàn)閮蓚€(gè)線程分別由不同的線程創(chuàng)建的,它們之間的變量不共享,產(chǎn)生了兩把不同的鎖
// 解決方法是在全局變量上加上 static 關(guān)鍵字,靜態(tài)變量存在方法區(qū),這個(gè)類(lèi)中的所有對(duì)象都共享同一個(gè)變量
重入鎖和不可重入鎖
重入鎖:即獲得鎖的線程可以進(jìn)入它擁有的鎖的同步代碼塊
不可重入鎖:即獲得鎖的線程,在方法中嘗試再次獲得鎖時(shí),獲取不到進(jìn)入阻塞狀態(tài)
死鎖產(chǎn)生的原因
同步中嵌套同步,同步鎖是一個(gè)重入鎖,就很有可能發(fā)生死鎖
為每個(gè)線程提供局部變量,解決線程安全問(wèn)題
ThreadLocal 底層采用 Map 來(lái)實(shí)現(xiàn),將當(dāng)前線程作為key,將值存儲(chǔ)到這個(gè) map 中
class Res {
private Integer count = 0;
ThreadLocal<Integer> integerThreadLocal = new ThreadLocal<Integer>() {
@Override
protected Integer initialValue() {
return 0;
}
};
public Integer getCount() {
int count = integerThreadLocal.get() + 1;
integerThreadLocal.set(count);
return count;
}
}
什么是原子性?
即一個(gè)或一組操作,要么全部執(zhí)行,執(zhí)行過(guò)程中不會(huì)被其他線程打斷,要么全部不執(zhí)行
什么是可見(jiàn)性?
多線程操作中一個(gè)線程修改了全局共享變量的值,其他線程能立馬得到修改后的值
什么是有序性?
程序執(zhí)行的順序按照代碼的先后順序執(zhí)行,一般來(lái)說(shuō)處理器為了提高程序運(yùn)行效率,可能會(huì)對(duì)輸入代碼進(jìn)行優(yōu)化,它不保證程序中各個(gè)語(yǔ)句的執(zhí)行先后順序同代碼中的順序一致,但是它會(huì)保證程序最終執(zhí)行結(jié)果和代碼順序執(zhí)行的結(jié)果是一致的
Java 內(nèi)存模型(JMM)
JMM 決定一個(gè)線程對(duì)一個(gè)共享變量做寫(xiě)操作時(shí),能否對(duì)另一個(gè)線程可見(jiàn)
主內(nèi)存:共享變量
本地內(nèi)存:共享變量副本
多線程做修改操作時(shí),首先從主內(nèi)存中拷貝一份副本到本地內(nèi)存中,當(dāng)線程修改本地內(nèi)存的值后,首先在本地內(nèi)存修改成功,然后再將修改后的結(jié)果刷新到主內(nèi)存中
可見(jiàn)性就是說(shuō)一旦某個(gè)線程修改了被 Volatile 修飾的變量,其他線程能立馬獲取到修改后的新值,在 Java 中為了加快程序的運(yùn)行效率,對(duì)一些變量的操作通常是在該線程的寄存器或者 CPU 緩存中進(jìn)行的,之后才會(huì)同步到主存,而加了 Volatile 關(guān)鍵字后會(huì)直接讀寫(xiě)內(nèi)存
注意:雖然該關(guān)鍵字能夠保證可見(jiàn)性,但不能保證原子性
特性:
Volatile 與 Synchronized 區(qū)別:
Volatile 雖然能保證可見(jiàn)性,但不能保證原子性
Synchronized 防止多個(gè)線程執(zhí)行同一塊代碼,影響執(zhí)行效率,就性能而言,Volatile 是高于 Synchronized 的。
但是 Volatile 是不能取代 Synchronized 的,因?yàn)?Volatile 不能保證原子性。
數(shù)據(jù)依賴(lài)
如果兩個(gè)操作同時(shí)操作一份變量,且這兩個(gè)操作其中有一個(gè)寫(xiě)操作,此時(shí)這兩個(gè)操作之間就存在數(shù)據(jù)依賴(lài)
名稱(chēng) | 代碼示例 | 說(shuō)明 |
---|---|---|
寫(xiě)后讀 | a = 1;b = a; | 寫(xiě)一個(gè)變量之后,再讀這個(gè)位置。 |
寫(xiě)后寫(xiě) | a = 1;a = 2; | 寫(xiě)一個(gè)變量之后,再寫(xiě)這個(gè)變量。 |
讀后寫(xiě) | a = b;b = 1; | 讀一個(gè)變量之后,再寫(xiě)這個(gè)變量 |
上面三種情況,只要更改操作的執(zhí)行順序,結(jié)果就會(huì)發(fā)生改變,編譯器和處理器可能會(huì)做重排序,在做重排序時(shí)會(huì)尊徐數(shù)據(jù)依賴(lài),所以編譯器和處理器不能對(duì)數(shù)據(jù)依賴(lài)的操作重排序,這里的數(shù)據(jù)依賴(lài)性?xún)H針對(duì)單個(gè)處理器中執(zhí)行的指令序列和單線程的操作,不同處理器之間和不同線程之間的數(shù)據(jù)依賴(lài)性不被編譯器和處理器考慮
as-if-serial語(yǔ)義
不管怎么重排,結(jié)果都不能改變
對(duì)多線程的影響
在單線程程序中,對(duì)存在數(shù)據(jù)依賴(lài)的操作做重排序不會(huì)影響結(jié)果,因?yàn)閱尉€程尊徐 as-if-serial 語(yǔ)義,但 as-if-serial 語(yǔ)義提到"不考慮不同處理器之間和不同線程之間的數(shù)據(jù)依賴(lài)",所以,指令重排可能會(huì)對(duì)多線程的結(jié)果產(chǎn)生影響
創(chuàng)新互聯(lián)www.cdcxhl.cn,專(zhuān)業(yè)提供香港、美國(guó)云服務(wù)器,動(dòng)態(tài)BGP最優(yōu)骨干路由自動(dòng)選擇,持續(xù)穩(wěn)定高效的網(wǎng)絡(luò)助力業(yè)務(wù)部署。公司持有工信部辦法的idc、isp許可證, 機(jī)房獨(dú)有T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確進(jìn)行流量調(diào)度,確保服務(wù)器高可用性。佳節(jié)活動(dòng)現(xiàn)已開(kāi)啟,新人活動(dòng)云服務(wù)器買(mǎi)多久送多久。
標(biāo)題名稱(chēng):如何結(jié)局線程安全問(wèn)題-創(chuàng)新互聯(lián)
文章出自:http://www.2m8n56k.cn/article30/pcgpo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供企業(yè)網(wǎng)站制作、網(wǎng)站設(shè)計(jì)、品牌網(wǎng)站設(shè)計(jì)、軟件開(kāi)發(fā)、品牌網(wǎng)站建設(shè)、用戶(hù)體驗(yàn)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:[email protected]。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容