并发编程实战-第二章学习
“共享”意味著變量可以由多個線程同時(shí)訪問,而“可變”則意味著變量的值再其聲明周期內(nèi)可以發(fā)生變化。
如果當(dāng)多個線程訪問同一個可變的狀態(tài)變量時(shí)沒有使用合適的同步,那么程序就會出現(xiàn)錯誤,有三種方式可以修復(fù)這個問題:
- 不在線程之間共享該狀態(tài)變量(有點(diǎn)扯,既然我要共享一個狀態(tài)變量,怎么可能不共享,只能說不共享肯定不會涉及狀態(tài)的同步)
- 將狀態(tài)變量修改為不可變的變量。
- 在訪問狀態(tài)變量時(shí)使用同步
什么是線程安全性
線程安全性的核心是正確性,即當(dāng)多個線程訪問某個類時(shí),這個類使用都能變現(xiàn)出正確的行為,那么這個類就是線程安全的。
在線程安全性一章中給出的定義:
當(dāng)多個線程訪問某個類時(shí),不管運(yùn)行環(huán)境采用何種調(diào)度凡是或者這些線程將如何交替執(zhí)行,并且在主調(diào)代碼中不需要任何額外的同步或協(xié)同,這個類都能變現(xiàn)出正確的行為,那么就稱這個類時(shí)線程安全的無狀態(tài)對象一定是線程安全的,無狀態(tài)即不包括任何域、也不包括任何對其他類中的域的引用。
?
原子性
原子操作是指,對于訪問同一個狀態(tài)的所有操作(包括該操作本身)來說,這個操作是一個原子的操作。(個人理解:所謂的原子,即最小單位,不可再分割,對于操作來說,及時(shí)是復(fù)合操作,同樣通過加鎖等其他方式將其捆綁在一起完成)
該節(jié)提出了產(chǎn)生數(shù)據(jù)不一致的問題,從而引出了,“先檢查后執(zhí)行”的操作,即通過一個可能失效的觀察結(jié)果來決定下一步的動作。通過舉例了兩個朋友相約咖啡廳的故事進(jìn)行了描述,通俗易懂,其中我個人認(rèn)為比較重要的一句----“當(dāng)你邁出前門時(shí),你在星巴克A的觀察結(jié)果將變得無效,因?yàn)樗赡芤呀?jīng)從后門進(jìn)入了星巴克,只是你不知道而已”。、
通過long的couut操作說明了符合操作,++count,涉及的操作為讀取-修改-寫入三部分操作,通過使用java.util.concurrent.atmoic包中的原子變量類AtomicLong來代替long類型來解決該問題是其成為一個線程安全的操作。
在實(shí)際情況中,應(yīng)盡可能地使用現(xiàn)有的線程安全對象(例如AtomicLong)來管理類的狀態(tài),與非線程安全的對象相比,判斷線程安全對象的可能狀態(tài)及其狀態(tài)轉(zhuǎn)換情況要更為容器,從而更容易維護(hù)和驗(yàn)證線程安全性
?加鎖機(jī)制
要保值狀態(tài)的一致性,就需要在單個原子操作中更新所有相關(guān)的狀態(tài)變量。
重入意味著獲取鎖的操作的粒度是線程,而不是調(diào)用。重入的一種實(shí)現(xiàn)方法是,為每個鎖關(guān)聯(lián)一個獲取計(jì)數(shù)值和一個所有者線程。
?一種常見的加鎖約定是,將所有的可變狀態(tài)都封裝在對象內(nèi)部,并通過對象的內(nèi)置鎖對所有訪問可變的代碼路徑進(jìn)行同步,使得在該對象上不會發(fā)生并發(fā)訪問。
需要注意的一點(diǎn)是即使是同步方法的符合操作,同樣會導(dǎo)致競態(tài)條件問題。如下代碼,雖然vector是的每個方法是原子方法,但是復(fù)合操作,同樣會導(dǎo)致出現(xiàn)數(shù)據(jù)不一致問題。
1 if ( !vector.contains(element)) 2 vector.add(element)?
遺留問題
1、原子性小節(jié)同樣提到了單例的實(shí)現(xiàn),該問題需要統(tǒng)一整理所有單例的實(shí)現(xiàn)方法,記一個遺留問題,下周解決
已經(jīng)復(fù)習(xí)了單例的相關(guān)知識,見:http://www.cnblogs.com/woniu4/p/8287484.html
?
轉(zhuǎn)載于:https://www.cnblogs.com/woniu4/p/8284244.html
總結(jié)
以上是生活随笔為你收集整理的并发编程实战-第二章学习的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Centos7 Zookeeper
- 下一篇: labview事件结构