淺談Java非阻塞同步機(jī)制和CAS
非阻塞同步的意思是多個(gè)線程在競(jìng)爭(zhēng)相同的數(shù)據(jù)時(shí)候不會(huì)發(fā)生阻塞,從而能夠在更加細(xì)粒度的維度上進(jìn)行協(xié)調(diào),從而極大的減少線程調(diào)度的開(kāi)銷,從而提升效率。非阻塞算法不存在鎖的機(jī)制也就不存在死鎖的問(wèn)題。
在基于鎖的算法中,如果一個(gè)線程持有了鎖,那么其他的線程將無(wú)法進(jìn)行下去。使用鎖雖然可以保證對(duì)資源的一致性訪問(wèn),但是在掛起和恢復(fù)線程的執(zhí)行過(guò)程中存在非常大的開(kāi)銷,如果鎖上面存在著大量的競(jìng)爭(zhēng),那么有可能調(diào)度開(kāi)銷比實(shí)際工作開(kāi)銷還要高。
悲觀鎖和樂(lè)觀鎖我們知道獨(dú)占鎖是一個(gè)悲觀鎖,悲觀鎖的意思就是假設(shè)最壞的情況,如果你不鎖定該資源,那么就有其他的線程會(huì)修改該資源。悲觀鎖雖然可以保證任務(wù)的順利執(zhí)行,但是效率不高。
樂(lè)觀鎖就是假設(shè)其他的線程不會(huì)更改要處理的資源,但是我們?cè)诟沦Y源的時(shí)候需要判斷該資源是否被別的線程所更改。如果被更改那么更新失敗,我們可以重試,如果沒(méi)有被更改,那么更新成功。
使用樂(lè)觀鎖的前提是假設(shè)大多數(shù)時(shí)間系統(tǒng)對(duì)資源的更新是不會(huì)產(chǎn)生沖突的。
樂(lè)觀鎖的原子性比較和更新操作,一般都是由底層的硬件支持的。
CAS大多數(shù)的處理器都實(shí)現(xiàn)了一個(gè)CAS指令(compare and swap),通常來(lái)說(shuō)一個(gè)CAS接收三個(gè)參數(shù),數(shù)據(jù)的現(xiàn)值V,進(jìn)行比較的值A(chǔ),準(zhǔn)備寫(xiě)入的值B。只有當(dāng)V和A相等的時(shí)候,才會(huì)寫(xiě)入B。無(wú)論是否寫(xiě)入成功,都會(huì)返回V。翻譯過(guò)來(lái)就是“我認(rèn)為V現(xiàn)在的值是A,如果是那么將V的值更新為B,否則不修改V的值,并告訴我現(xiàn)在V的值是多少。”
這就是CAS的含義,JDK中的并發(fā)類是通過(guò)使用Unsafe類來(lái)使用CAS的,我們可以自己構(gòu)建一個(gè)并發(fā)類,如下所示:
public class CasCounter { private static final Unsafe unsafe = Unsafe.getUnsafe(); private static final long valueOffset; private volatile int value; static {try { valueOffset = unsafe.objectFieldOffset (CasCounter.class.getDeclaredField('value'));} catch (Exception ex) { throw new Error(ex); } } public CasCounter(int initialValue) {value = initialValue; } public CasCounter() { } public final int get() {return value; } public final void set(int newValue) {value = newValue; } public final boolean compareAndSet(int expect, int update) {return unsafe.compareAndSwapInt(this, valueOffset, expect, update); }}
上面的例子中,我們定義了一個(gè)原子操作compareAndSet, 它內(nèi)部調(diào)用了unsafe的compareAndSwapInt方法。
看起來(lái)上面的CAS使用比直接使用鎖復(fù)雜,但實(shí)際上在JVM中實(shí)現(xiàn)鎖定時(shí)需要遍歷JVM中一條非常復(fù)雜的代碼路徑,并可能導(dǎo)致操作系統(tǒng)級(jí)的鎖定,線程掛機(jī)和上下文切換等操作。在最好的情況下,鎖定需要執(zhí)行一次CAS命令。
CAS的主要缺點(diǎn)就是需要調(diào)用者自己來(lái)處理競(jìng)爭(zhēng)問(wèn)題(重試,回退,放棄),而在鎖中可以自動(dòng)處理這些問(wèn)題。
前面的文章我們也講到了原子變量,原子變量的底層就是使用CAS。
以上就是淺談Java非阻塞同步機(jī)制和CAS的詳細(xì)內(nèi)容,更多關(guān)于Java非阻塞同步機(jī)制和CAS的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!
相關(guān)文章:
1. HTML DOM setInterval和clearInterval方法案例詳解2. 詳解CSS偽元素的妙用單標(biāo)簽之美3. HTML <!DOCTYPE> 標(biāo)簽4. javascript xml xsl取值及數(shù)據(jù)修改第1/2頁(yè)5. html小技巧之td,div標(biāo)簽里內(nèi)容不換行6. 告別AJAX實(shí)現(xiàn)無(wú)刷新提交表單7. 詳解盒子端CSS動(dòng)畫(huà)性能提升8. CSS Hack大全-教你如何區(qū)分出IE6-IE10、FireFox、Chrome、Opera9. XML入門精解之結(jié)構(gòu)與語(yǔ)法10. msxml3.dll 錯(cuò)誤 800c0019 系統(tǒng)錯(cuò)誤:-2146697191解決方法
