java线程同步——竞争条件的荔枝+锁对象
【0】README
0.1) 本文描述轉(zhuǎn)自 core java volume 1, 源代碼為原創(chuàng),旨在理解 java線程同步——競(jìng)爭(zhēng)條件的荔枝+鎖對(duì)象 的相關(guān)知識(shí); 
 0.2) for full source code, please visit https://github.com/pacosonTang/core-java-volume/blob/master/chapter14/ThreadFive.java
【1】競(jìng)爭(zhēng)條件的荔枝
1.1)某銀行有若干個(gè)賬戶(我們這里設(shè)置為4個(gè)),且初始余額均為10000; 賬戶間存在著轉(zhuǎn)賬操作; 
 Attention):在模擬這個(gè)程序的過(guò)程中, 不清楚在某一時(shí)刻某銀行的賬戶轉(zhuǎn)賬多少錢(qián),但是其總金額應(yīng)該是不變的, 因?yàn)槲覀兯龅囊磺胁贿^(guò)是從銀行的一個(gè)賬戶轉(zhuǎn)賬到另一個(gè)賬戶(干貨——無(wú)論怎樣轉(zhuǎn)賬,總金額應(yīng)該是不變的,始終為40000)。 
  
 對(duì)上述運(yùn)行結(jié)果的分析(Analysis):
- A1)問(wèn)題在于這不是一個(gè)原子操作, 該指令可能被如下處理: 
 - step1)將 account[to] 加載到寄存器;
- step2)增加 amount 到 account[to]上;
- step3)將結(jié)果寫(xiě)回 account[to];
 
- A2)現(xiàn)在線程1 執(zhí)行step1 + step2, 然后CPU切換到執(zhí)行線程2; 
 - A2.1)假設(shè)線程2修改了account[to]的值;
- A2.2)之后,線程1被喚醒,然后進(jìn)行 step3;
 
- A3)那顯然, 線程1的step3操作重寫(xiě)了 線程2的寫(xiě)入結(jié)果(線程1擦除線程2所做的更新), 所以就出現(xiàn)了最終的總金額不等于 40000的錯(cuò)誤結(jié)果;
- A4)如果要保持結(jié)果的合理性,只需要達(dá)到一個(gè)目的,就是將對(duì)賬戶余額的訪問(wèn)加以限制,每次只能有一個(gè)線程在訪問(wèn)。這樣就能保證賬戶中余額數(shù)據(jù)的合理性了。
1.2)解決方法:
- 1.2.1)使用同步塊(synchronized):在使用同步代碼塊時(shí)候,應(yīng)該指定在哪個(gè)對(duì)象上同步,也就是說(shuō)要獲取哪個(gè)對(duì)象的鎖。例如:(干貨——無(wú)論怎樣轉(zhuǎn)賬,總金額應(yīng)該是不變的,始終為40000)。 
 
- 1.2.2)使用同步方法:(干貨——無(wú)論怎樣轉(zhuǎn)賬,總金額應(yīng)該是不變的,始終為40000)。 
 
【2】鎖對(duì)象
2.1)有兩種方法防止代碼塊受并發(fā)訪問(wèn)的干擾:
- 2.1.1) synchronized 關(guān)鍵字, 構(gòu)造同步塊,或是同步方法;(如1.2中解決方法 所示)
- 2.1.2) java 5.0 引入的 ReentrantLock 類(lèi);
2.2)用ReentrantLock保護(hù)代碼塊的基本結(jié)構(gòu)
myLock.lock() try {} finally {myLock.unlock() }- 2.2.1)這一結(jié)構(gòu)確保了 任何時(shí)刻只有一個(gè)線程進(jìn)入臨界區(qū)域, 一旦一個(gè)線程封鎖了鎖對(duì)象,其他任何線程都無(wú)法通過(guò)lock語(yǔ)句。 當(dāng)其他線程調(diào)用 lock 時(shí), 它們會(huì)被阻塞,直到第一個(gè)線程釋放鎖對(duì)象;
Warning)把解鎖操作包括在了 finally 子句中是至關(guān)重要的。 如果在臨界區(qū)的代碼拋出異常, 鎖必須被釋放, 否則, 其他線程將永遠(yuǎn)阻塞下去; 
  
 Attention)
- A1)鎖是可重入的, 因?yàn)榫€程可以重復(fù)地獲得已持有的鎖;
- A2)鎖保持一個(gè)持有計(jì)數(shù)來(lái)跟蹤對(duì) lock 方法的嵌套調(diào)用, 線程在每一次調(diào)用lock 都要調(diào)用 unlock 來(lái)釋放鎖;
- A3)由于這一特性, 被一個(gè)鎖保護(hù)起來(lái)的代碼可以調(diào)用另一個(gè)使用相同的鎖的方法; 
 
總結(jié)
以上是生活随笔為你收集整理的java线程同步——竞争条件的荔枝+锁对象的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
 
                            
                        - 上一篇: 笑看天下什么意思 笑看天下意思是什么
- 下一篇: 阿维塔发布智驾征珠峰战报 九天成功抵达珠
