java.util.concurrent.AtomicInteger

AtomicInteger,一個提供原子操做的Integer的類。在Java語言中,++i和i++操做並非線程安全的,在使用的時候,不可避免的會用到synchronized關鍵字。而AtomicInteger則經過一種線程安全的加減操做接口。安全

來看AtomicInteger提供的接口。數據結構

//獲取當前的值併發

public final int get()優化

//取當前的值,並設置新的值this

 public final int getAndSet(int newValue)atom

//獲取當前的值,並自增spa

 public final int getAndIncrement()線程

//獲取當前的值,並自減orm

public final int getAndDecrement()接口

//獲取當前的值,並加上預期的值

public final int getAndAdd(int delta)

... ...

爲何說atomicInteger是線程安全的呢?

在AtomicInteger的源碼中相關的代碼以下:

Java代碼  收藏代碼

  1. // setup to use Unsafe.compareAndSwapInt for updates  

  2. private static final Unsafe unsafe = Unsafe.getUnsafe();  

  上面這行代碼是獲取Unsafe實例的。通常狀況下,咱們是拿不到該類的實例的,固然jdk庫裏面是能夠隨意使用的。

 

 

Java代碼  收藏代碼

  1. static {  

  2.      try {  

  3.        valueOffset = unsafe.objectFieldOffset  

  4.            (AtomicInteger.class.getDeclaredField("value"));  

  5.      } catch (Exception ex) { throw new Error(ex); }  

  6.    }  

 

  上面這幾行代碼,是用來獲取AtomicInteger實例中的value屬性在內存中的位置。這裏使用了Unsafe的objectFieldOffset方法。這個方法是一個本地方法, 該方法用來獲取一個給定的靜態屬性的位置。

 

Java代碼  收藏代碼

  1. public native long objectFieldOffset(Field f);  

 

這裏有個疑問,爲何須要獲取屬性在內存中的位置?經過查看AtomicInteger源碼發現,在這樣幾個地方使用到了這個valueOffset值:

 

Java代碼  收藏代碼

  1. public final void lazySet(int newValue) {  

  2.         unsafe.putOrderedInt(this, valueOffset, newValue);  

  3.     }  

 

Java代碼  收藏代碼

  1. public final boolean compareAndSet(int expect, int update) {  

  2.     return unsafe.compareAndSwapInt(this, valueOffset, expect, update);  

  3.     }  

 

 

Java代碼  收藏代碼

  1. public final boolean weakCompareAndSet(int expect, int update) {  

  2.     return unsafe.compareAndSwapInt(this, valueOffset, expect, update);  

  3.     }  

 

  查找資料後,發現lazySet方法大多用在併發的數據結構中,用於低級別的優化。compareAndSet這個方法多見於併發控制中,簡稱CAS(Compare And Swap),意思是若是valueOffset位置包含的值與expect值相同,則更新valueOffset位置的值爲update,並返回true,不然不更新,返回false。

這裏能夠舉個例子來講明compareAndSet的做用,如支持併發的計數器,在進行計數的時候,首先讀取當前的值,假設值爲a,對當前值 + 1獲得b,可是+1操做完之後,並不能直接修改原值爲b,由於在進行+1操做的過程當中,可能會有其它線程已經對原值進行了修改,因此在更新以前須要判斷原值是否是等於a,若是不等於a,說明有其它線程修改了,須要從新讀取原值進行操做,若是等於a,說明在+1的操做過程當中,沒有其它線程來修改值,咱們就能夠放心的更新原值了。

相關文章
相關標籤/搜索