JDK併發包溫故而知新系列(一)—— 競態條件與記憶體可見性
阿新 • • 發佈:2019-10-02
併發問題
併發問題是指多執行緒讀寫共享記憶體的時候,產生結果不可預期的情況,併發問題的產生的原因可以歸結為兩種,一是因為競態條件,二是因為記憶體可見性、
競態條件
什麼是競態條件
競態條件,官方解釋是如果程式執行順序的改變會影響最終結果,這就是一個競態條件。
這句話有點抽象,描述的有點抽象,我個人對競態條件的理解是多個執行緒在競爭同一系列資源的使用權,因為使用都是有時間的,不是咔嚓一下完成的,對於每個執行緒來說它能夠正確執行的條件就是要求從獲取資源到使用資源完成都是原子性的,不允許其他執行緒來中途改變資源從而影響了原子性,每個執行緒都需要這種條件,我把這種多個執行緒對於共享資源獲取到操作完成的原子性的需求叫做競態條件。
針對競態條件問題的應對思想
結合自己所學,總結一下應對競態條件的思想:
- 通過路由避免競爭,這反映在併發包中有ConcurrentHashMap的分段鎖機制、Java8對Cas的優化如LongAdder代替AtomicLong等等,很多地方都是運用了這種思想降低競爭資源粒度。
- 對資源的獲取以及使用資源進行序列化,通過鎖、CAS、佇列來序列化獲取資源和操作資源的操作。
- 寫時複製避免讀寫競爭。比如ArrayList的寫操作,沒有必要在寫的過程不讓讀,通過寫時複製是可以同時進行讀的。對應的併發容器CopyOnWriteArrayList就是採用的寫時複製原理使得隨時都可以讀,類似的還有InnoDb的MVCC快照讀、各種讀快取機制如eureka的多級快取機制。等下講到的JVM針對共享變數主記憶體、工作記憶體都是類似的思想。
先