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

歡迎訪問 生活随笔!

生活随笔

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

java

Java并发编程实战~原子类

發布時間:2024/7/23 java 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java并发编程实战~原子类 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

對于簡單的原子性問題,還有一種無鎖方案,先看看如何利用原子類解決累加器問題。

public class Test {AtomicLong count = new AtomicLong(0);public void add10K() {int idx = 0;while(idx++ < 10000) {count.getAndIncrement();}}}

無鎖方案相對互斥鎖方案,最大的好處就是性能。

無鎖方案的實現原理

其實原子類性能高的秘密很簡單,硬件支持而已。CPU 為了解決并發問題,提供了 CAS 指令(CAS,全稱是 Compare And Swap,即“比較并交換”)。CAS 指令包含 3 個參數:共享變量的內存地址 A、用于比較的值 B 和共享變量的新值 C;并且只有當內存中地址 A 處的值等于 B 時,才能將內存中地址 A 處的值更新為新值 C。作為一條 CPU 指令,CAS 指令本身是能夠保證原子性的。

你可以通過下面 CAS 指令的模擬代碼來理解 CAS 的工作原理。在下面的模擬程序中有兩個參數,一個是期望值 expect,另一個是需要寫入的新值 newValue,只有當目前 count的值和期望值 expect 相等時,才會將 count 更新為 newValue

class SimulatedCAS{int count;public synchronized int cas(int expect, int newValue){// 讀目前 count 的值int curValue = count;// 比較目前 count 值是否 == 期望值if(curValue == expect){// 如果是,則更新 count 的值count = newValue;}// 返回寫入前的值return curValue;}}

使用 CAS 來解決并發問題,一般都會伴隨著自旋,而所謂自旋,其實就是循環嘗試。

class SimulatedCAS{volatile int count;// 實現 count+=1public void addOne(){do {newValue = count+1; //①}while(count != cas(count,newValue) //②}// 模擬實現 CAS,僅用來幫助理解public synchronized int cas(int expect, int newValue){// 讀目前 count 的值int curValue = count;// 比較目前 count 值是否 == 期望值if(curValue == expect){// 如果是,則更新 count 的值count= newValue;}// 返回寫入前的值return curValue;} }

但是在 CAS 方案中,有一個問題可能會常被你忽略,那就是ABA的問題。什么是 ABA 問題呢?

假設 count 原本是 A,線程 T1 在執行完代碼①處之后,執行代碼②處之前,有可能 count 被線程 T2 更新成了 B,之后又被 T3 更新回了 A,這樣線程T1 雖然看到的一直是 A,但是其實已經被其他線程更新過了,這就是 ABA 問題。

Java 如何實現原子化的 count += 1

在 Java 1.8 版本中,getAndIncrement() 方法會轉調 unsafe.getAndAddLong() 方法。這里 this 和 valueOffset 兩個參數可以唯一確定共享變量的內存地址。

final long getAndIncrement() {return unsafe.getAndAddLong(this, valueOffset, 1L); }

unsafe.getAndAddLong() 方法的源碼如下

public final long getAndAddLong(Object o, long offset, long delta){long v;do {// 讀取內存中的值v = getLongVolatile(o, offset);} while (!compareAndSwapLong(o, offset, v, v + delta));return v; }// 原子性地將變量更新為 x // 條件是內存中的值等于 expected // 更新成功則返回 true native boolean compareAndSwapLong(Object o, long offset, long expected,long x);

原子類概覽

?1. 原子化的基本數據類型

getAndIncrement() // 原子化 i++ getAndDecrement() // 原子化的 i-- incrementAndGet() // 原子化的 ++i decrementAndGet() // 原子化的 --i // 當前值 +=delta,返回 += 前的值 getAndAdd(delta) // 當前值 +=delta,返回 += 后的值 addAndGet(delta) //CAS 操作,返回是否成功 compareAndSet(expect, update) // 以下四個方法 // 新值可以通過傳入 func 函數來計算 getAndUpdate(func) updateAndGet(func) getAndAccumulate(x,func) accumulateAndGet(x,func)

總結

以上是生活随笔為你收集整理的Java并发编程实战~原子类的全部內容,希望文章能夠幫你解決所遇到的問題。

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