日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

[Java多线程]-J.U.C.atomic包下的AtomicInteger,AtomicLong等类的源码解析

發布時間:2024/9/5 java 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [Java多线程]-J.U.C.atomic包下的AtomicInteger,AtomicLong等类的源码解析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Atomic原子類:為基本類型的封裝類Boolean,Integer,Long,對象引用等提供原子操作.

一、Atomic包下的所有類如下表:

類摘要
AtomicBoolean可以用原子方式更新的?boolean?值。
AtomicInteger可以用原子方式更新的?int?值。
AtomicIntegerArray可以用原子方式更新其元素的?int?數組。
AtomicIntegerFieldUpdater<T>基于反射的實用工具,可以對指定類的指定?volatile int?字段進行原子更新。
AtomicLong可以用原子方式更新的?long?值。
AtomicLongArray可以用原子方式更新其元素的?long?數組。
AtomicLongFieldUpdater<T>基于反射的實用工具,可以對指定類的指定?volatile long?字段進行原子更新。
AtomicMarkableReference<V>AtomicMarkableReference?維護帶有標記位的對象引用,可以原子方式對其進行更新。
AtomicReference<V>可以用原子方式更新的對象引用。
AtomicReferenceArray<E>可以用原子方式更新其元素的對象引用數組。
AtomicReferenceFieldUpdater<T,V>基于反射的實用工具,可以對指定類的指定?volatile?字段進行原子更新。
AtomicStampedReference<V>AtomicStampedReference?維護帶有整數“標志”的對象引用,可以用原子方式對其進行更新。

?

二、AtomicInteger源碼分析和基本的方法使用:

Atomicinteger類中的方法列表:

構造方法摘要
AtomicInteger()?
??????????創建具有初始值?0?的新 AtomicInteger。
AtomicInteger(int?initialValue)?
??????????創建具有給定初始值的新 AtomicInteger。
方法摘要
?intaddAndGet(int?delta)?
??????????以原子方式將給定值與當前值相加。
?booleancompareAndSet(int?expect, int?update)?
??????????如果當前值?==?預期值,則以原子方式將該值設置為給定的更新值。
?intdecrementAndGet()?
??????????以原子方式將當前值減 1。
?doubledoubleValue()?
??????????以?double?形式返回指定的數值。
?floatfloatValue()?
??????????以?float?形式返回指定的數值。
?intget()?
??????????獲取當前值。
?intgetAndAdd(int?delta)?
??????????以原子方式將給定值與當前值相加。
?intgetAndDecrement()?
??????????以原子方式將當前值減 1。
?intgetAndIncrement()?
??????????以原子方式將當前值加 1。
?intgetAndSet(int?newValue)?
??????????以原子方式設置為給定值,并返回舊值。
?intincrementAndGet()?
??????????以原子方式將當前值加 1。
?intintValue()?
??????????以?int?形式返回指定的數值。
?voidlazySet(int?newValue)?
??????????最后設置為給定值。
?longlongValue()?
??????????以?long?形式返回指定的數值。
?voidset(int?newValue)?
??????????設置為給定值。
?StringtoString()?
??????????返回當前值的字符串表示形式。
?booleanweakCompareAndSet(int?expect, int?update)?
??????????如果當前值?==?預期值,則以原子方式將該設置為給定的更新值。
從類 java.lang.Number?繼承的方法
byteValue,?shortValue
從類 java.lang.Object?繼承的方法
clone,?equals,?finalize,?getClass,?hashCode,?notify,?notifyAll,?wait,?wait,?wait

AtomicInteger源碼:

/** ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.*********************//******* Written by Doug Lea with assistance from members of JCP JSR-166* Expert Group and released to the public domain, as explained at* http://creativecommons.org/publicdomain/zero/1.0/*/package java.util.concurrent.atomic; import sun.misc.Unsafe;/*** An {@code int} value that may be updated atomically. See the* {@link java.util.concurrent.atomic} package specification for* description of the properties of atomic variables. An* {@code AtomicInteger} is used in applications such as atomically* incremented counters, and cannot be used as a replacement for an* {@link java.lang.Integer}. However, this class does extend* {@code Number} to allow uniform access by tools and utilities that* deal with numerically-based classes.** @since 1.5* @author Doug Lea */ public class AtomicInteger extends Number implements java.io.Serializable {private static final long serialVersionUID = 6214790243416807050L;// setup to use Unsafe.compareAndSwapInt for updatesprivate static final Unsafe unsafe = Unsafe.getUnsafe();private static final long valueOffset;static {try {valueOffset = unsafe.objectFieldOffset(AtomicInteger.class.getDeclaredField("value"));} catch (Exception ex) { throw new Error(ex); }}private volatile int value;/*** Creates a new AtomicInteger with the given initial value.** @param initialValue the initial value*/public AtomicInteger(int initialValue) {value = initialValue;}/*** Creates a new AtomicInteger with initial value {@code 0}.*/public AtomicInteger() {}/*** Gets the current value.** @return the current value*/public final int get() {return value;}/*** Sets to the given value.** @param newValue the new value*/public final void set(int newValue) {value = newValue;}/*** Eventually sets to the given value.** @param newValue the new value* @since 1.6*/public final void lazySet(int newValue) {unsafe.putOrderedInt(this, valueOffset, newValue);}/*** Atomically sets to the given value and returns the old value.** @param newValue the new value* @return the previous value*/public final int getAndSet(int newValue) {for (;;) {int current = get();if (compareAndSet(current, newValue))return current;}}/*** Atomically sets the value to the given updated value* if the current value {@code ==} the expected value.** @param expect the expected value* @param update the new value* @return true if successful. False return indicates that* the actual value was not equal to the expected value.*/public final boolean compareAndSet(int expect, int update) {return unsafe.compareAndSwapInt(this, valueOffset, expect, update);}/*** Atomically sets the value to the given updated value* if the current value {@code ==} the expected value.** <p>May <a href="package-summary.html#Spurious">fail spuriously</a>* and does not provide ordering guarantees, so is only rarely an* appropriate alternative to {@code compareAndSet}.** @param expect the expected value* @param update the new value* @return true if successful.*/public final boolean weakCompareAndSet(int expect, int update) {return unsafe.compareAndSwapInt(this, valueOffset, expect, update);}/*** Atomically increments by one the current value.** @return the previous value*/public final int getAndIncrement() {for (;;) {int current = get();int next = current + 1;if (compareAndSet(current, next))return current;}}/*** Atomically decrements by one the current value.** @return the previous value*/public final int getAndDecrement() {for (;;) {int current = get();int next = current - 1;if (compareAndSet(current, next))return current;}}/*** Atomically adds the given value to the current value.** @param delta the value to add* @return the previous value*/public final int getAndAdd(int delta) {for (;;) {int current = get();int next = current + delta;if (compareAndSet(current, next))return current;}}/*** Atomically increments by one the current value.** @return the updated value*/public final int incrementAndGet() {for (;;) {int current = get();int next = current + 1;if (compareAndSet(current, next))return next;}}/*** Atomically decrements by one the current value.** @return the updated value*/public final int decrementAndGet() {for (;;) {int current = get();int next = current - 1;if (compareAndSet(current, next))return next;}}/*** Atomically adds the given value to the current value.** @param delta the value to add* @return the updated value*/public final int addAndGet(int delta) {for (;;) {int current = get();int next = current + delta;if (compareAndSet(current, next))return next;}}/*** Returns the String representation of the current value.* @return the String representation of the current value.*/public String toString() {return Integer.toString(get());}public int intValue() {return get();}public long longValue() {return (long)get();}public float floatValue() {return (float)get();}public double doubleValue() {return (double)get();}} AtomicInteger

其中的屬性:

private static final long serialVersionUID = 6214790243416807050L;// setup to use Unsafe.compareAndSwapInt for updatesprivate static final Unsafe unsafe = Unsafe.getUnsafe();private static final long valueOffset;static {try {valueOffset = unsafe.objectFieldOffset(AtomicInteger.class.getDeclaredField("value"));} catch (Exception ex) { throw new Error(ex); }}private volatile int value;

unsafe :java中的sun.misc.Unsafe包,提供了安全訪問內存的方法。這些方法提供給java訪問底層的JNI(java-native-interface),因為這些方法最終是調用c/c++實現。
valueOffset:指向相對于對象起始位置的偏移量(內存中)可以理解為引用指向的內存,通過這個值可以去內存中查找某個引用在內存的值。
value:引用的當前值[預期值E]

方法示例:

public class AtomTest {private static AtomicInteger num = new AtomicInteger(0);public static void main(String[] args) {System.out.println(num.compareAndSet(0, 1));//比較并設置,用0與內存中的值比較,相等的話,修改值為1System.out.println(num.compareAndSet(0, 1));//比較并設置,用0與內存中的值比較,相等的話,修改值為1System.out.println(num.get());;//獲取初值num.set(2);//設置初值,System.out.println(num.get());System.out.println(num.decrementAndGet());//獲取值自減返回減1之后的值System.out.println(num.addAndGet(2));//獲取值添加2然后返回添加后的值System.out.println(num.getAndIncrement());//獲取值并且自增,返回的是自增前的值System.out.println(num.getAndAdd(5));System.out.println(num.getAndDecrement());System.out.println(num.getAndSet(100));System.out.println(num.get());} }

運行結果:

true false 1 2 1 3 3 4 9 8 100

初始化的時候賦值為0,調用從compareAndSwap(0,1)之后返回true,compareAndSwap比較并交換,比較結果相同則修改值并返回TRUE不通則返回FALSE。

看看這個方法的源碼:

/*** Atomically sets the value to the given updated value* if the current value {@code ==} the expected value.** @param expect the expected value* @param update the new value* @return true if successful. False return indicates that* the actual value was not equal to the expected value.*/public final boolean compareAndSet(int expect, int update) {return unsafe.compareAndSwapInt(this, valueOffset, expect, update);}

compareAndSwap:當前引用值和與要更新的值以及對象,和偏移量做參數去更新內存,根據對象和偏移量可以找到引用的內存值與引用值(期望值)作比較,相等則說明這個值在此對象獲得后未被修改,那么我們就可以更新,則結果為true。這個方法就是傳說中的CAS,CAS相較于synchonrized提供了一種無鎖的線程安全保證。

示例中的前兩個操作是一樣的,我們可以理解為兩個線程同時更新值為1,前一個快一點,發現更新的時候內存值未變則更新,等到第二個更新的時候原始值0與內存值(此時內存值變為1了)比較則失敗返回FALSE并且不進行更新。這樣就保證了一致性,而我們看到變量的值value使用voliate修飾的,保證了數據的內存可見性(一個線程修改其他線程可見)。所以多個線程并發的時候這個類代替Integer能夠保證安全。

這個操作非常像數據庫的樂觀鎖,給每個表添加一個version版本號,修改數據后要持久化先查詢看版本號一致不,一致的話則持久化,不一致則重新獲取值進行修改。

三、AtomicLong源碼以及與AtomicInteger的不同:

package java.util.concurrent.atomic; import sun.misc.Unsafe;/*** A {@code long} value that may be updated atomically. See the* {@link java.util.concurrent.atomic} package specification for* description of the properties of atomic variables. An* {@code AtomicLong} is used in applications such as atomically* incremented sequence numbers, and cannot be used as a replacement* for a {@link java.lang.Long}. However, this class does extend* {@code Number} to allow uniform access by tools and utilities that* deal with numerically-based classes.** @since 1.5* @author Doug Lea*/ public class AtomicLong extends Number implements java.io.Serializable {private static final long serialVersionUID = 1927816293512124184L;// setup to use Unsafe.compareAndSwapLong for updatesprivate static final Unsafe unsafe = Unsafe.getUnsafe();private static final long valueOffset;/*** Records whether the underlying JVM supports lockless* compareAndSwap for longs. While the Unsafe.compareAndSwapLong* method works in either case, some constructions should be* handled at Java level to avoid locking user-visible locks.*/static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8();/*** Returns whether underlying JVM supports lockless CompareAndSet* for longs. Called only once and cached in VM_SUPPORTS_LONG_CAS.*/private static native boolean VMSupportsCS8();static {try {valueOffset = unsafe.objectFieldOffset(AtomicLong.class.getDeclaredField("value"));} catch (Exception ex) { throw new Error(ex); }}private volatile long value;/*** Creates a new AtomicLong with the given initial value.** @param initialValue the initial value*/public AtomicLong(long initialValue) {value = initialValue;}/*** Creates a new AtomicLong with initial value {@code 0}.*/public AtomicLong() {}/*** Gets the current value.** @return the current value*/public final long get() {return value;}/*** Sets to the given value.** @param newValue the new value*/public final void set(long newValue) {value = newValue;}/*** Eventually sets to the given value.** @param newValue the new value* @since 1.6*/public final void lazySet(long newValue) {unsafe.putOrderedLong(this, valueOffset, newValue);}/*** Atomically sets to the given value and returns the old value.** @param newValue the new value* @return the previous value*/public final long getAndSet(long newValue) {while (true) {long current = get();if (compareAndSet(current, newValue))return current;}}/*** Atomically sets the value to the given updated value* if the current value {@code ==} the expected value.** @param expect the expected value* @param update the new value* @return true if successful. False return indicates that* the actual value was not equal to the expected value.*/public final boolean compareAndSet(long expect, long update) {return unsafe.compareAndSwapLong(this, valueOffset, expect, update);}/*** Atomically sets the value to the given updated value* if the current value {@code ==} the expected value.** <p>May <a href="package-summary.html#Spurious">fail spuriously</a>* and does not provide ordering guarantees, so is only rarely an* appropriate alternative to {@code compareAndSet}.** @param expect the expected value* @param update the new value* @return true if successful.*/public final boolean weakCompareAndSet(long expect, long update) {return unsafe.compareAndSwapLong(this, valueOffset, expect, update);}/*** Atomically increments by one the current value.** @return the previous value*/public final long getAndIncrement() {while (true) {long current = get();long next = current + 1;if (compareAndSet(current, next))return current;}}/*** Atomically decrements by one the current value.** @return the previous value*/public final long getAndDecrement() {while (true) {long current = get();long next = current - 1;if (compareAndSet(current, next))return current;}}/*** Atomically adds the given value to the current value.** @param delta the value to add* @return the previous value*/public final long getAndAdd(long delta) {while (true) {long current = get();long next = current + delta;if (compareAndSet(current, next))return current;}}/*** Atomically increments by one the current value.** @return the updated value*/public final long incrementAndGet() {for (;;) {long current = get();long next = current + 1;if (compareAndSet(current, next))return next;}}/*** Atomically decrements by one the current value.** @return the updated value*/public final long decrementAndGet() {for (;;) {long current = get();long next = current - 1;if (compareAndSet(current, next))return next;}}/*** Atomically adds the given value to the current value.** @param delta the value to add* @return the updated value*/public final long addAndGet(long delta) {for (;;) {long current = get();long next = current + delta;if (compareAndSet(current, next))return next;}}/*** Returns the String representation of the current value.* @return the String representation of the current value.*/public String toString() {return Long.toString(get());}public int intValue() {return (int)get();}public long longValue() {return get();}public float floatValue() {return (float)get();}public double doubleValue() {return (double)get();}} AtomicLong源碼

關于AtomicLong的用法和AtomicInteger類似:

不同之處在于多了下面一部分:一個靜態的Boolean值VM_SUPPORTS_LONG_CAS,調用一個 native方法VMSupportCS8()返回虛擬機是否支持Long類型的無鎖CAS機制

/*** Records whether the underlying JVM supports lockless* compareAndSwap for longs. While the Unsafe.compareAndSwapLong* method works in either case, some constructions should be* handled at Java level to avoid locking user-visible locks.*/static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8();/*** Returns whether underlying JVM supports lockless CompareAndSet* for longs. Called only once and cached in VM_SUPPORTS_LONG_CAS.*/private static native boolean VMSupportsCS8();

從這里可以看出不同的VM支持的數據類型可能有所差別,因為CAS需要硬件系統的支持。

四、AtomicReference源碼及使用:

/*** An object reference that may be updated atomically. See the {@link* java.util.concurrent.atomic} package specification for description* of the properties of atomic variables.* @since 1.5* @author Doug Lea* @param <V> The type of object referred to by this reference*/ public class AtomicReference<V> implements java.io.Serializable {private static final long serialVersionUID = -1848883965231344442L;private static final Unsafe unsafe = Unsafe.getUnsafe();private static final long valueOffset;static {try {valueOffset = unsafe.objectFieldOffset(AtomicReference.class.getDeclaredField("value"));} catch (Exception ex) { throw new Error(ex); }}private volatile V value;/*** Creates a new AtomicReference with the given initial value.** @param initialValue the initial value*/public AtomicReference(V initialValue) {value = initialValue;}/*** Creates a new AtomicReference with null initial value.*/public AtomicReference() {}/*** Gets the current value.** @return the current value*/public final V get() {return value;}/*** Sets to the given value.** @param newValue the new value*/public final void set(V newValue) {value = newValue;}/*** Eventually sets to the given value.** @param newValue the new value* @since 1.6*/public final void lazySet(V newValue) {unsafe.putOrderedObject(this, valueOffset, newValue);}/*** Atomically sets the value to the given updated value* if the current value {@code ==} the expected value.* @param expect the expected value* @param update the new value* @return true if successful. False return indicates that* the actual value was not equal to the expected value.*/public final boolean compareAndSet(V expect, V update) {return unsafe.compareAndSwapObject(this, valueOffset, expect, update);}/*** Atomically sets the value to the given updated value* if the current value {@code ==} the expected value.** <p>May <a href="package-summary.html#Spurious">fail spuriously</a>* and does not provide ordering guarantees, so is only rarely an* appropriate alternative to {@code compareAndSet}.** @param expect the expected value* @param update the new value* @return true if successful.*/public final boolean weakCompareAndSet(V expect, V update) {return unsafe.compareAndSwapObject(this, valueOffset, expect, update);}/*** Atomically sets to the given value and returns the old value.** @param newValue the new value* @return the previous value*/public final V getAndSet(V newValue) {while (true) {V x = get();if (compareAndSet(x, newValue))return x;}}/*** Returns the String representation of the current value.* @return the String representation of the current value.*/public String toString() {return String.valueOf(get());}} AtomicReference源碼

除了類型是個對象的之外,方法使用和AtomicInteger一模一樣:

AtomicReference的使用:

import java.util.concurrent.atomic.AtomicReference;public class AtomTest {private static AtomicReference<Pig> pigtest;public static void main(String[] args) {Pig pig = new Pig("豬堅強", 2);Pig pig2 = new Pig("豬八戒", 2);System.out.println("pig_hashCode:"+pig.hashCode());System.out.println("pig2_hashCode:"+pig2.hashCode());AtomTest.pigtest = new AtomicReference<Pig>(pig);System.out.println(pigtest.get().toString());System.out.println(pigtest.get().hashCode());System.out.println(pigtest.compareAndSet(pig, pig2));System.out.println(pigtest.compareAndSet(pig, pig2));System.out.println(pigtest.get().toString());System.out.println(pigtest.get().hashCode());} }

運行結果:

pig_hashCode:779824645 pig2_hashCode:420110874 [豬堅強,2] 779824645 true false [豬八戒,2] 420110874

第一步:先獲取pigTest的toString(),和hashCode,結果是【豬堅強,2】,hashCode:779824645【我們發現hashCode居然==pig_hashCode】

第二步:進行CAS修改為pig2結果為true,再進行一次結果為FALSE,

第三步:獲取pigTest的toString(),和hashCode,結果是【豬八戒,2】,hashCode:420110874【我們發現hashCode居然==pig2_hashCode】

結果說明了:pigtest是一個指向對象引用的引用,利用CAS操作可以修改pigTest指向的對象引用從而改變自身指向的對象。第一次CAS成功將pigtest指向的pig修改成了pig2.第二次CAS操作失敗了,可以保證多線程并發時的安全問題。

五、總結:

  Atomic包下內容并不復雜,一句話來說就是提供了CAS無鎖的安全訪問機制。表現出來的是通過期望值E與內存值M作比較,相同則修改內存值M為更新值U。四個參數:當前對象this,偏移量V,期望值E,更新值U。

  利用CAS+voliate+native的機制保證數據操作的原子性,可見性和一致性。voliate使變量可見,CAS調用unsafe中的native方法訪問系統底層的實現。unsafe中的這些方法直接操作內存,運用不當可能造成很大的問題。

  其實從Atomic包中的原子類的探索中,只是想引出CAS這個概念,CAS同樣提供了一種線程安全的機制,而它不同于Synchonrized,synchonrized被稱之為重量級鎖,原因是因為粒度太強,加鎖就代表著線程阻塞,高并發訪問時帶來的性能問題是硬傷。

  為了解決這種問題出現了兩種機制:一種就是CAS,另一種是鎖優化。

  CAS是將阻塞下降到了底層CPU上(純屬個人理解,因為看到有權威是說存在阻塞的,可能讓別的線程知道已經更改了數據并且更新失敗也是一種阻塞吧),語言層面訪問效率遠遠低于系統內部硬件上,盡管同樣是阻塞,在系統內部加鎖解鎖的效率要高很多。但是需要的是硬件支持,不過現在絕大部分CPU都已經支持CAS了。

  unsafe類:http://www.cnblogs.com/mickole/articles/3757278.html大家可以看這篇博客。

轉載于:https://www.cnblogs.com/NextNight/p/6600343.html

總結

以上是生活随笔為你收集整理的[Java多线程]-J.U.C.atomic包下的AtomicInteger,AtomicLong等类的源码解析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。