一。鎖的劣勢
(1) 在JDK1.5之前都是使用synchronized關鍵字保證同步的,這種通過使用一致的鎖定協議來協調對共享狀態的訪問,可以確保無論哪個線程持有守
護變量的鎖,都采用獨占的方式來訪問這些變量
(2)如果出現多個線程同時訪問鎖,則一些線程將被掛起,當線程恢復執行時,必須等待其它線程執行完他們的時間片以后才能被調度執行,在掛起和
恢復執行過程中存在着很大的開銷
(3)當一個線程正在等待鎖時,它不能做任何事
(4)如果一個線程在持有鎖的情況下被延遲執行,那么所有需要這個鎖的線程都無法執行下去
(5)如果被阻塞的線程優先級高,而持有鎖的線程優先級低,將會導致優先級反轉
二。volatile的優勢
(6)與鎖相比,volatile變量是一和更輕量級的同步機制,因為在使用這些變量時不會發生上下文切換和線程調度等操作
(7)volatile變量也存在一些局限:不能用於構建原子的復合操作,因此當一個變量依賴舊值時就不能使用volatile變量
三。CAS操作
(8) Compare and Swap,CPU指令,CAS的語義是“我認為V的值應該為A,如果是,那么將V的值更新為B,否則不修改並告訴V的值實際為多少”
(9)CAS是樂觀鎖技術,當多個線程嘗試使用CAS同時更新同一個變量時,只有其中一個線程能更新變量的值,而其它線程都失敗,失敗的線程並不會被掛
起,而是被告知這次競爭中失敗。這種基於沖突檢測的樂觀並發策略,當線程數目非常多的情況下,失敗的概率會指數型增加。
public final int getAndIncrement() { for (;;) { int current = get(); int next = current + 1; if (compareAndSet(current, next)) return current; } }
四。JVM對CAS的支持
(10)在JDK1.5中引入了底層的支持,在Integer,Long等類型上都公開了 CAS的操作,並且JVM把它們編譯為底層硬件提供的最有效的方法,
在運行CAS的平台上,運行時把它們編譯為相應的機器指令,如果處理器不支持CAS指 令,那么JVM將使用自旋鎖。
(11)在CAS操作中,在更新之前先判斷V的值是否仍然A,如果是的話就繼續執行更新操作,但是有的時候還需要知道“自從上次看到V的值為A
以后,這個值是否發生了變化”
(12)解決方案:更新兩個值:【引用,版本號】,即使這個值由A變為B,然后為變為A,版本號也是不同的。AtomicStampedReference更
新一個“對象-引用”二元組,通過在引用上加上“版本號”,從而避免ABA問題,AtomicMarkableReference將更新一個“對象引用-布爾值”的二元 組。
相關內容
IBM系列: Java理論和實踐