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());      }    }

參考文獻

https://github.com/giantray/stackoverflow-java-top-qa/blob/master/contents/what-is-a-serialversionuid-and-why-should-i-use-it.md