atomicBoolean源碼分析
- 2019 年 10 月 5 日
- 筆記
版權聲明:本文為部落客原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
本文鏈接:https://blog.csdn.net/qq_37933685/article/details/80889270
個人部落格:https://suveng.github.io/blog/
atomicBoolean源碼分析
注意:解析都放在源碼裡面
源碼
package java.util.concurrent.atomic; import sun.misc.Unsafe; /** 一個boolean值可以用原子更新。 有關原子變數屬性的描述,請參閱java.util.concurrent.atomic包規範。 一個AtomicBoolean用於諸如原子更新標誌的應用程式,不能用作替代Boolean 。 從以下版本開始: 1.5 另請參見: Serialized Form * * @since 1.5 * @author Doug Lea */ public class AtomicBoolean implements java.io.Serializable { private static final long serialVersionUID = 4654671469794556979L; /*serialVersionUID 有什麼作用?該如何使用? serialVersionUID 是實現 Serializable 介面而來的,而 Serializable 則是應用於Java 對象序列化/反序列化。對象的序列化主要有兩種用途: 1. 把對象序列化成位元組碼,保存到指定介質上(如磁碟等) 2. 用於網路傳輸 詳情看下面參考文獻1 這是鏈接https://github.com/giantray/stackoverflow-java-top-qa/blob/master/contents/what-is-a-serialversionuid-and-why-should-i-use-it.md */ // 設置為使用Unsafe.compareAndSwapInt進行更新 private static final Unsafe unsafe = Unsafe.getUnsafe(); // valueOffset 是 value這個欄位的相對於atomicBoolean這個對象的偏移量 private static final long valueOffset; // 下面這段靜態程式碼塊是用於獲取valueOffset static { try { valueOffset = unsafe.objectFieldOffset (AtomicBoolean.class.getDeclaredField("value")); } catch (Exception ex) { throw new Error(ex); } } // 這個就是AtomicBoolean的關鍵值,value private volatile int value; /**構造方法 * 用給定的初始值創建一個新的 AtomicBoolean 。 * *參數 initialValue - 初始值 */ public AtomicBoolean(boolean initialValue) { value = initialValue ? 1 : 0; } /**構造方法 * 創建一個新的 AtomicBoolean ,初始值為 false 。 */ public AtomicBoolean() { } /** * 返回當前值 * * @return 當前值 */ public final boolean get() { return value != 0; } /* 這裡的返回時(value!=0)的布爾值 為什麼初始值為false是? value的值為0,value=0,所以(value!=0)為false,所以初始值為false */ /** * 如果當前值為 ==的預期值,則將該值原子設置為給定的更新值。 * * @param expect expect - 預期值 * @param update update - 新的價值 * @return true如果成功 */ public final boolean compareAndSet(boolean expect, boolean update) { int e = expect ? 1 : 0; int u = update ? 1 : 0; return unsafe.compareAndSwapInt(this, valueOffset, e, u); } /* 這裡直接用unsafe類的CAS操作改變值,關於unsafe類的說明: * Unsafe類是用來在任意記憶體地址位置處讀寫數據,可見,對於普通用戶來說,使用起來還是比較危險的。 * 關於CAS演算法的說明:https://blog.csdn.net/qq_37933685/article/details/80871395 */ /** * 如果當前值為==為預期值,則將該值原子設置為給定的更新值。 可能會失敗,所以只是很少適合替代compareAndSet 。 */ public boolean weakCompareAndSet(boolean expect, boolean update) { int e = expect ? 1 : 0; int u = update ? 1 : 0; return unsafe.compareAndSwapInt(this, valueOffset, e, u); } /* 延續上面的提問,為什麼可能會失敗?這裡給我跳轉到jdk 的javadoc,我把原文發出來,裡面很詳細,這裡簡單描述一下 這裡是鏈接:https://blog.csdn.net/qq_37933685/article/details/80888972 一個原子類也支援weakCompareAndSet方法,該方法有適用性的限制。在一些平台上,在正常情況下weak版本比compareAndSet更高效, 但是不同的是任何給定的weakCompareAndSet方法的調用都可能會返回一個虛假的失敗( 無任何明顯的原因 )。一個失敗的返回意味著,操作將會重新執行如果需要的話, 重複操作依賴的保證是當變數持有expectedValue的值並且沒有其他的執行緒也嘗試設置這個值將最終操作成功。( 一個虛假的失敗可能是由於記憶體衝突的影響,而和預期值(expectedValue)和當前的值是否相等無關 )。 此外weakCompareAndSet並不會提供排序的保證,即通常需要用於同步控制的排序保證。然而,這個方法可能在修改計數器或者統計,這種修改無關於其他happens-before的程式中非常有用。 當一個執行緒看到一個通過weakCompareAndSet修改的原子變數時,它不被要求看到其他變數的修改,即便該變數的修改在weakCompareAndSet操作之前。 weakCompareAndSet實現了一個變數原子的讀操作和有條件的原子寫操作,但是它不會創建任何happen-before排序, 所以該方法不提供對weakCompareAndSet操作的目標變數以外的變數的在之前或在之後的讀或寫操作的保證。 */ /** * 無條件地設置為給定的值。 * * @param newValue newValue - 新的價值 */ public final void set(boolean newValue) { value = newValue ? 1 : 0; } /** * 最終設定為給定值。 * * @param newValue newValue - 新的價值 * @since 1.6 */ public final void lazySet(boolean newValue) { int v = newValue ? 1 : 0; unsafe.putOrderedInt(this, valueOffset, v); } /** * 將原子設置為給定值並返回上一個值。 * * @param newValue newValue - 新值 * @return 以前的值 */ public final boolean getAndSet(boolean newValue) { boolean prev; do { prev = get(); } while (!compareAndSet(prev, newValue)); return prev; } /** * 返回當前值的String表示形式。 * 重寫: toString在類別 Object * @return the String representation of the current value */ public String toString() { return Boolean.toString(get()); } }