1、原子性問題
原子操作定義:原子操作可以是一個步驟,也可以是多個操作步驟,但是其順序不可以被打亂,也不可以被切割而只執行其中的一部分(不可中斷性)。將整個操作視爲一個整體是原子性的核心特徵。
存在競爭條件,線程不安全,需要轉變原子操作才能安全。方式:循環CAS、鎖;上例只是針對一個變量的原子操作改進,我們也可以實現更大邏輯的原子操作。
解決:
a、J.U.C包內的原子操作封裝類
CAS機制
Compare and swap比較和交換。屬於硬件同步原語,處理器提供了基本內存操作的原子性保證。CAS操作需要輸入兩個數值,一箇舊值A和一個新值B,在操作期間先比較下舊值有沒有發生變化,如果沒有發生變化,才交換成新值,發生了變化則不交換。
JAVA中的sun.misc.Unsafe類,提供了compareAndSwapInt()和compareAndSwapLong()等幾個方法實現CAS。
CAS拿到內存中的值,如果A和V的值是否變化,沒有變化,將B的值替換成內存地址上的值,如果變化了則不交換。
CAS問題:
(1)循環+CAS,自旋的實現讓所有線程都處於高頻運行,掙錢CPU執行時間的狀態。如果操作長時間不成功,會帶來很大的CPU資源消耗。
(2)僅針對單個變量的操作,不能用於多個變量來實現原子操作。
b、鎖的方式
Synchronized關鍵字
public void add1(){ synchronized (this) { i++; } }
Lock ReentrantLock
Lock lock = new ReentrantLock();
public void add2() {
lock.lock();
try {
i++;
} finally {
lock.unlock();
}
}