原子性
原子(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 關鍵字,并且該修飾能保證該對象一定是線程安全的。
private static final int i;
private final int j;
static {
i = 0;
}
{
// 也可以選擇在構造函數中初始化
j = 0;
}
有序性
是指如果在本線程内觀察,所有的操作都是有序的;如果在一個線程中觀察另一個線程,所有的操作都是無序的。前半句是指“線程内表現為串行的語義(as is serial)”,後半句是指“指令重排序”現象和“工作記憶體與主記憶體同步延遲”現象。
從應用場景來看,JVM 保證有序性主要有以下方式:
- volatile 關鍵字,它本身就包含了禁止指令重排序的語義。
- synchronized 等鎖機制,同步塊的有序性是由“一個變量在同一個時刻隻允許一條線程對其進行 lock 操作”這條規則獲得的。