深入淺出ConcurrentHashMap1.8+CAS+volatile


1.深入淺出CAS

前言

CAS(Compare and Swap),即比較並替換,實現並發算法時常用到的一種技術,Doug lea大神在java同步器中大量使用了CAS技術,鬼斧神工的實現了多線程執行的安全性。CAS原理(也可以理解為樂觀鎖)保證了原子

CAS的思想很簡單:三個參數,一個當前內存值V、舊的預期值A、即將更新的值B,當且僅當預期值A和內存值V相同時,將內存值修改為B並返回true,否則什么都不做,並返回false。

CAS缺點

CAS存在一個很明顯的問題,即ABA問題。

問題:如果變量V初次讀取的時候是A,並且在准備賦值的時候檢查到它仍然是A,那能說明它的值沒有被其他線程修改過了嗎?

如果在這段期間曾經被改成B,然后又改回A,那CAS操作就會誤認為它從來沒有被修改過。針對這種情況,java並發包中提供了一個帶有標記的原子引用類AtomicStampedReference,它可以通過控制變量值的版本來保證CAS的正確性。

2.volatile關鍵字

前言

volatile作為java中的關鍵詞之一,用以聲明變量的值可能隨時會別的線程修改,使用volatile修飾的變量會強制將修改的值立即寫入主存,主存中值的更新會使緩存中的值失效(非volatile變量不具備這樣的特性,非volatile變量的值會被緩存,線程A更新了這個值,線程B讀取這個變量的值時可能讀到的並不是是線程A更新后的值)。volatile會禁止指令重排。

 

  2.1 volatile特性

 

volatile具有可見性、有序性,不具備原子性。

 

注意,volatile不具備原子性,這是volatile與java中的synchronized、java.util.concurrent.locks.Lock最大的功能差異,這一點在面試中也是非常容易問到的點。

 

下面來分別看下可見性、有序性、原子性:

 

原子性:如果你了解事務,那這個概念應該好理解。原子性通常指多個操作不存在只執行一部分的情況,如果全部執行完成那沒毛病,如果只執行了一部分,那對不起,你得撤銷(即事務中的回滾)已經執行的部分。可見性:當多個線程訪問同一個變量x時,線程1修改了變量x的值,線程1、線程2...線程n能夠立即讀取到線程1修改后的值。有序性:即程序執行時按照代碼書寫的先后順序執行。在Java內存模型中,允許編譯器和處理器對指令進行重排序,但是重排序過程不會影響到單線程程序的執行,卻會影響到多線程並發執行的正確性。(本文不對指令重排作介紹,但不代表它不重要,它是理解JAVA並發原理時非常重要的一個概念)。3.volatile適用場景

 

適用於對變量的寫操作不依賴於當前值,對變量的讀取操作不依賴於非volatile變量。適用於讀多寫少的場景(因為讀操作不需要原子性)可用作狀態標志。JDK中volatie應用:JDK中ConcurrentHashMap的Entry的value和next被聲明為volatile,AtomicLong中的value被聲明為volatile。AtomicLong通過CAS原理(也可以理解為樂觀鎖)保證了原子性。    

  2.2 volatile VS synchronized

  • volatile本質是在告訴jvm當前變量在寄存器(工作內存)中的值是不確定的,需要從主存中讀取; synchronized則是鎖定當前變量,只有當前線程可以訪問該變量,其他線程被阻塞住。
  • volatile僅能使用在變量級別;synchronized則可以使用在變量、方法、和類級別的
  • volatile僅能實現變量的修改可見性,不能保證原子性;而synchronized則可以保證變量的修改可見性和原子性
  • volatile不會造成線程的阻塞;synchronized可能會造成線程的阻塞。
  • volatile標記的變量不會被編譯器優化;synchronized標記的變量可以被編譯器優化

深入淺出ConcurrentHashMap1.8  (轉載 https://www.jianshu.com/p/c0642afe03e0)

對於上面的文章的總結

  1. jdk1.7 ConcurrentHashMap采用 分段鎖的機制,實現並發的更新操作,底層采用數組+鏈表的存儲結構,jdk1.8的實現已經拋棄了Segment分段鎖機制,利用CAS+Synchronized來保證並發更新的安全,底層采用數組+鏈表+紅黑樹的存儲結構。

  2. 鍵值對節點使用的Node

  • Node:保存key,value及key的hash值的數據結構。

 

其中value和next都用volatile修飾,保證並發的可見性。

3. put操作采用CAS+synchronized實現並發插入或更新操作

4.其他的和hashMap 差不多。

5.線程安全,不允許有null值null 鍵

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM