Java多線程之原子性、可見性與有序性

原子性

原子(atom)指化學反應不可再分的基本微粒,原子在化學反應中不可分割。原子操作指的是不可分割的整體,多線程的

原子性指的是沒有其他線程能夠中斷或檢查正在原子操作中的變量。

從內存模型來看,直接保證的原子性變量操作包括 read、load、assign、use、store 和 write,我們大致可以認為基本數據類型的訪問讀寫是具備原子性的。

從應用場景來看,JVM 保證原子性操作的主要有以下方式:

  • synchronized 關鍵字。鎖操作,基於 monitorenter 和 monitorexit 字節碼指令。
  • AQS 鎖機制。比如 ReentrantLock、ReentrantReadWriteLock 等。
  • CAS 實現。比如 java.util.concurrent.atomic 包中的諸多實現。
  • volatile 關鍵字。修飾變量,輕量鎖機制,僅能保證對單個變量的操作具有原子性,複合操作不具備原子性。

可見性

可見性是指當一個線程修改了共享變量的值,其他線程能夠立即得知這個修改。

從應用場景來看,JVM 保證可見性主要有以下方式:

  • volatile 關鍵字,它是如何保證可見性的呢?當對 volatile 變量寫的時候,會將當前處理器緩存行的數據寫回到系統內存;當對 volatile 變量讀的時候,會將當前處理器緩存行的數據置為無效,因此要從系統內存中讀取變量值。
  • synchronized 等鎖機制。同步塊的可見性是由“對一個變量執行 unlock 操作之前,必須先把此變量同步回主內存中(執行 store、write 操作)”這條規則獲得的。
  • final 關鍵字。被 final 修飾的字段在構造器中一旦初始化完成,並且構造器沒有把“this”的引用傳遞出去,那在其他線程中就能看到 final 關鍵字。

有序性

有序性是指如果在本線程內觀察,所有的操作都是有序的;如果在一個線程中觀察另一個線程,所有的操作都是無序的。前半句是指“線程內表現為串行的語義(as is serial)”,後半句是指“指令重排序”現象和“工作內存與主內存同步延遲”現象。

從應用場景來看,JVM 保證有序性主要有以下方式:

  • volatile 關鍵字,它本身就包含了禁止指令重排序的語義。
  • synchronized 等鎖機制,同步塊的有序性是由“一個變量在同一個時刻只允許一條線程對其進行 lock 操作”這條規則獲得。


分享到:


相關文章: