最常需要解決的問題是i++ 這個語義在多執行緒中是不安全的。雖然從語法上看上去是乙個操作,實際上分為了三步。取出i的值,i+1,將i+1的計算結果賦值給i。假設i的初始值為5,一種不安全的情況如下:-1
2345
6執行緒1
i(5)
i+1(6)
i(6)
執行緒2i(5)
i+1(6)
i(6)
也就是說兩個執行緒併發執行i++操作,所得的結果都是6 !而我們期望應該是乙個是6,乙個是7。如果這個用於資料庫主鍵的生成,這將導致嚴重的主鍵衝突。
// setup to use unsafe.compareandswapint for updates
private static final unsafe unsafe = unsafe.getunsafe();
private static final long valueoffset;
static catch (exception ex)
}private volatile int value;
public final int incrementandget()
value:用volatile修飾使得變數對所有執行緒可見,代表實際值,atomicinteger.get()就是返回這個的值。
incrementandget():這是也就是我們常用的保證原子操作遞增方法,它實際上呼叫了unsafe.getandaddint()
unsafe類並不能直接檢視到原始碼,只能通過反編譯來看。
public final native boolean compareandswapint(object object, long valueoffset, int expected, int update);
public final int
getandaddint(object object, long valueoffset, int increament) while(!this.compareandswapint(object, valueoffset, expected, expected + increament));
return expected;
}
先看看compareandswapint方法,方法用native修飾,表示是乙個本地方法,呼叫的是cas指令執行,這是整個過程是乙個原子操作。功能是如果位址(由object和valueoffset共同確定)中的值與expected相同,則設定改位址的值為update,並返回true,否則不更新且返回false。
再看看getandaddint(),在這個方法中呼叫了this.getintvolatile(object, valueoffset),表示獲取位址中的值,那麼整個getandaddint()方法的語義是:
1.獲取到物件中儲存value位址的值
2.然後再回去比較是否相等,相等則更新,否則從1開始重試直到成功。
為什麼atomicinteger操作並不會出現執行緒問題:當兩個執行緒同時進入do-while迴圈中後,只有第乙個執行緒能執行更新操作成功並退出迴圈,第二個執行緒試圖執行賦值操作因為位址中的值不一致而不會更新,只能重新執行迴圈,重新執行迴圈獲得到的是最新的value值,所以此處並不會出現執行緒問題。
該類的中其它方法與本文類似,故不重複分析。
注:本文原始碼為jdk1.8
AbstractCollection原始碼分析
abstractcollection抽象類提供了collection的骨架實現,collection分析請看 這裡直接看它的 是如何實現的.public abstract iterator iterator 該方法沒有實現.public abstract int size 該方法沒有實現.publi...
ThreadPoolExecutor原始碼閱讀
執行緒池解決兩個問題 一是復用執行緒,減少建立銷毀執行緒帶來系統開銷 二是限定系統資源使用邊界,避免大量執行緒消耗盡系統記憶體 適用於互不依賴,執行時間短,不需要對執行緒控制操作的執行緒 新增任務時,1.若執行緒數量小於corepoolsize,則新增執行緒執行任務 2.若執行緒數量大於等於core...
OrangePi One Android 原始碼編譯
一 系統環境搭建參照 二 lichee原始碼編譯 1.檢視help build.sh h2.配置核心 cd linux 3.4 make arch arm menuconfig 進入配置頁面,上下移動列表,空格是選擇列表,左右移動選擇退出選項 3.首次編譯執行清除 在 lichee linux3.4...