CAS:
Compare and Swap, 翻譯成比較并交換。
java.util.concurrent包中借助CAS實(shí)現(xiàn)了區(qū)別于synchronouse同步鎖的一種樂(lè)觀鎖。
CAS實(shí)現(xiàn)原理:
CAS有3個(gè)操作數(shù),內(nèi)存值V,舊的預(yù)期值A(chǔ),要修改的新值B。當(dāng)且僅當(dāng)預(yù)期值A(chǔ)和內(nèi)存值V相同時(shí),將內(nèi)存值V修改為B,否則什么都不做。
boolean compareAndSwap( V, A, B){
if (V != A) {
return false;
} else {
V = B;
return true;
}
}
這個(gè)過(guò)程在硬件層面實(shí)現(xiàn)的,Java主要用JNI類 UNSAFE實(shí)現(xiàn)的。
這里不詳細(xì)描述其具實(shí)現(xiàn),詳情:UNSAFE詳情
CAS 缺點(diǎn):
ABA問(wèn)題:就是當(dāng)修改,從A改成B,再?gòu)腂改回A。那么CAS算法會(huì)當(dāng)他沒(méi)有變化,但實(shí)際上數(shù)據(jù)是變化了。
解決方法: 加入版本控制,每次操作都有版本號(hào)。
處理過(guò)程: 先檢查值有沒(méi)變化,如果沒(méi)變,再檢查版本號(hào)。循環(huán)時(shí)間過(guò)長(zhǎng):CAS如果長(zhǎng)時(shí)間不成功,就會(huì)浪費(fèi)掉非常多的CPU資源。
解決方法:pause指令。有兩個(gè)作用:
a. 可以延遲流水線執(zhí)行指令(de-pipeline),使CPU不會(huì)消耗過(guò)多的執(zhí)行資源,延遲的時(shí)間取決于具體實(shí)現(xiàn)的版本,在一些處理器上延遲時(shí)間是零。
b. 可以避免在退出循環(huán)的時(shí)候因內(nèi)存順序沖突(memory order violation)而引起CPU流水線被清空(CPU pipeline flush),從而提高CPU的執(zhí)行效率。只能保證一個(gè)共享變量的原子操作:當(dāng)操作一個(gè)共享變量時(shí),可以使用CAS,但一個(gè)原子操作有多個(gè)共享變量時(shí)。我們只能用鎖來(lái)解決問(wèn)題,獲取把多個(gè)共享變量合并成一個(gè)共享變量。
解決方法:
a. 使用鎖控制幾個(gè)共享變量;
b. 合并幾個(gè)共享變量使用CAS。
concurrent包的實(shí)現(xiàn)
由于java的CAS同時(shí)具有 volatile 讀和volatile寫(xiě)的內(nèi)存語(yǔ)義,因此Java線程之間的通信現(xiàn)在有了下面四種方式:
- A線程寫(xiě)volatile變量,隨后B線程讀這個(gè)volatile變量。
- A線程寫(xiě)volatile變量,隨后B線程用CAS更新這個(gè)volatile變量。
- A線程用CAS更新一個(gè)volatile變量,隨后B線程用CAS更新這個(gè)volatile變量。
- A線程用CAS更新一個(gè)volatile變量,隨后B線程讀這個(gè)volatile變量。
Java的CAS會(huì)使用現(xiàn)代處理器上提供的高效機(jī)器級(jí)別原子指令,這些原子指令以原子方式對(duì)內(nèi)存執(zhí)行讀-改-寫(xiě)操作,這是在多處理器中實(shí)現(xiàn)同步的關(guān)鍵(從本質(zhì)上來(lái)說(shuō),能夠支持原子性讀-改-寫(xiě)指令的計(jì)算機(jī)器,是順序計(jì)算圖靈機(jī)的異步等價(jià)機(jī)器,因此任何現(xiàn)代的多處理器都會(huì)去支持某種能對(duì)內(nèi)存執(zhí)行原子性讀-改-寫(xiě)操作的原子指令)。同時(shí),volatile變量的讀/寫(xiě)和CAS可以實(shí)現(xiàn)線程之間的通信。把這些特性整合在一起,就形成了整個(gè)concurrent包得以實(shí)現(xiàn)的基石。如果我們仔細(xì)分析concurrent包的源代碼實(shí)現(xiàn),會(huì)發(fā)現(xiàn)一個(gè)通用化的實(shí)現(xiàn)模式:
- 首先,聲明共享變量為volatile;
- 然后,使用CAS的原子條件更新來(lái)實(shí)現(xiàn)線程之間的同步;
- 同時(shí),配合以volatile的讀/寫(xiě)和CAS所具有的volatile讀和寫(xiě)的內(nèi)存語(yǔ)義來(lái)實(shí)現(xiàn)線程之間的通信。
AQS,非阻塞數(shù)據(jù)結(jié)構(gòu)和原子變量類(java.util.concurrent.atomic包中的類),這些concurrent包中的基礎(chǔ)類都是使用這種模式來(lái)實(shí)現(xiàn)的,而concurrent包中的高層類又是依賴于這些基礎(chǔ)類來(lái)實(shí)現(xiàn)的。從整體來(lái)看,concurrent包的實(shí)現(xiàn)示意圖如下:

參考文檔:
http://www.cnblogs.com/zhuawang/p/4196904.html
concurrent包的實(shí)現(xiàn)內(nèi)容完全轉(zhuǎn)載
http://www.cnblogs.com/zhuawang/p/4196904.html