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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

atomic的实现原理

發(fā)布時間:2023/12/16 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 atomic的实现原理 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

? ?
? ? ?在多線程的場景中,我們需要保證數(shù)據(jù)安全,就會考慮同步的方案,通常會使用synchronized或者lock來處理,使用了synchronized意味著內核態(tài)的一次切換。這是一個很重的操作。

? ? ?有沒有一種方式,可以比較便利的實現(xiàn)一些簡單的數(shù)據(jù)同步,比如計數(shù)器等等。concurrent包下的atomic提供我們這么一種輕量級的數(shù)據(jù)同步的選擇。

class MyThread implements Runnable {static AtomicInteger ai=new AtomicInteger(0);public void run() {for (int m = 0; m < 1000000; m++) {ai.getAndIncrement();}} };public class TestAtomicInteger {public static void main(String[] args) throws InterruptedException {MyThread mt = new MyThread();Thread t1 = new Thread(mt);Thread t2 = new Thread(mt);t1.start();t2.start();Thread.sleep(500);System.out.println(MyThread.ai.get());} }

? ? ? 在以上代碼中,使用AtomicInteger聲明了一個全局變量,并且在多線程中進行自增,代碼中并沒有進行顯示的加鎖。以上代碼的輸出結果,永遠都是2000000。如果將AtomicInteger換成Integer,打印結果基本都是小于2000000。
? ? ? 也就說明AtomicInteger聲明的變量,在多線程場景中的自增操作是可以保證線程安全的。接下來我們分析下其原理。

原理

? ? ? 這里,我們來看看AtomicInteger是如何使用非阻塞算法來實現(xiàn)并發(fā)控制的。
? ? ? AtomicInteger的關鍵域只有一下3個:

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() {}...... }

? ? ? 這里, unsafe是java提供的獲得對對象內存地址訪問的類,注釋已經(jīng)清楚的寫出了,它的作用就是在更新操作時提供“比較并替換”的作用。實際上就是AtomicInteger中的一個工具。

? ? ? valueOffset是用來記錄value本身在內存的編譯地址的,這個記錄,也主要是為了在更新操作在內存中找到value的位置,方便比較。

? ? ?value是用來存儲整數(shù)的時間變量,這里被聲明為volatile。volatile只能保證這個變量的可見性。不能保證他的原子性。

? ? ?可以看看getAndIncrement這個類似i++的函數(shù),可以發(fā)現(xiàn),是調用了UnSafe中的getAndAddInt。

/*** Atomically increments by one the current value.** @return the previous value*/public final int getAndIncrement() {return unsafe.getAndAddInt(this, valueOffset, 1);}/*** 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) {return unsafe.getAndSetInt(this, valueOffset, newValue);}public final int getAndSetInt(Object var1, long var2, int var4) {int var5;do {var5 = this.getIntVolatile(var1, var2);//使用unsafe的native方法,實現(xiàn)高效的硬件級別CAS} while(!this.compareAndSwapInt(var1, var2, var5, var4));return var5;}

? ? ? 如何保證原子性:自旋 + CAS(樂觀鎖)。在這個過程中,通過compareAndSwapInt比較更新value值,如果更新失敗,重新獲取舊值,然后更新。


優(yōu)缺點

? ? ? CAS相對于其他鎖,不會進行內核態(tài)操作,有著一些性能的提升。但同時引入自旋,當鎖競爭較大的時候,自旋次數(shù)會增多。cpu資源會消耗很高。

? ? ? 換句話說,CAS+自旋適合使用在低并發(fā)有同步數(shù)據(jù)的應用場景。

?

Java 8做出的改進和努力

? ? ? 在Java 8中引入了4個新的計數(shù)器類型,LongAdder、LongAccumulator、DoubleAdder、DoubleAccumulator。他們都是繼承于Striped64。

? ? ?在LongAdder 與AtomicLong有什么區(qū)別?
Atomic*遇到的問題是,只能運用于低并發(fā)場景。因此LongAddr在這基礎上引入了分段鎖的概念。可以參考《JDK8系列之LongAdder解析》一起看看做了什么。

? ? ?大概就是當競爭不激烈的時候,所有線程都是通過CAS對同一個變量(Base)進行修改,當競爭激烈的時候,會將根據(jù)當前線程哈希到對于Cell上進行修改(多段鎖)。

/*** Table of cells. When non-null, size is a power of 2.*/transient volatile Cell[] cells;/*** Base value, used mainly when there is no contention, but also as* a fallback during table initialization races. Updated via CAS.*/transient volatile long base; /*** Padded variant of AtomicLong supporting only raw accesses plus CAS.** JVM intrinsics note: It would be possible to use a release-only* form of CAS here, if it were provided.*/@sun.misc.Contended static final class Cell {volatile long value;Cell(long x) { value = x; }final boolean cas(long cmp, long val) {return UNSAFE.compareAndSwapLong(this, valueOffset, cmp, val);}// Unsafe mechanicsprivate static final sun.misc.Unsafe UNSAFE;private static final long valueOffset;static {try {UNSAFE = sun.misc.Unsafe.getUnsafe();Class<?> ak = Cell.class;valueOffset = UNSAFE.objectFieldOffset(ak.getDeclaredField("value"));} catch (Exception e) {throw new Error(e);}}}

? ? ?可以看到大概實現(xiàn)原理是:通過CAS樂觀鎖保證原子性,通過自旋保證當次修改的最終修改成功,通過降低鎖粒度(多段鎖)增加并發(fā)性能。

?

?

Refrence:
https://mp.weixin.qq.com/s/aw6OXC9wkxH42rCywNd7yQ

?

?

總結

以上是生活随笔為你收集整理的atomic的实现原理的全部內容,希望文章能夠幫你解決所遇到的問題。

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