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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

无锁并发的CAS为何如此优秀?

發布時間:2025/3/16 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 无锁并发的CAS为何如此优秀? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Talk is cheap

CAS(Compare And Swap),即比較并交換。是解決多線程并行情況下使用鎖造成性能損耗的一種機制,CAS操作包含三個操作數——內存位置(V)、預期原值(A)和新值(B)。如果內存位置的值與預期原值相匹配,那么處理器會自動將該位置值更新為新值。否則,處理器不做任何操作。無論位置V的值是否等于A, 都將返回V原有的值。

CAS的含義是”我認為V的值應該是A,如果是,那我將V的值更新為B,否則不修改并告訴V的值實際是多少“

Show you my code

在單線程環境中分別使用無鎖,加鎖以及cas進行十組5億次累加運算,然后打印出平均耗時。

/*** cas對比加鎖測試** @author Jann Lee* @date 2019-11-21 0:12**/ public class CasTest {@Testpublic void test() {long times = 500_000_000;// 記錄耗時List<Long> elapsedTime4NoLock = new ArrayList<>(10);List<Long> elapsedTime4Synchronized = new ArrayList<>(10);List<Long> elapsedTime4ReentrantLock = new ArrayList<>(10);List<Long> elapsedTime4Cas = new ArrayList<>(10);// 進行10組試驗for (int j = 0; j < 10; j++) {// 無鎖long startTime = System.currentTimeMillis();for (long i = 0; i < times; i++) {}long endTime = System.currentTimeMillis();elapsedTime4NoLock.add(endTime - startTime);// synchronized 關鍵字(隱式鎖)startTime = endTime;for (long i = 0; i < times; ) {i = addWithSynchronized(i);}endTime = System.currentTimeMillis();elapsedTime4Synchronized.add(endTime - startTime);// ReentrantLock 顯式鎖startTime = endTime;ReentrantLock lock = new ReentrantLock();for (long i = 0; i < times; ) {i = addWithReentrantLock(i, lock);}endTime = System.currentTimeMillis();elapsedTime4ReentrantLock.add(endTime - startTime);// cas(AtomicLong底層是用cas實現)startTime = endTime;AtomicLong atomicLong = new AtomicLong();while (atomicLong.getAndIncrement() < times) {}endTime = System.currentTimeMillis();elapsedTime4Cas.add(endTime - startTime);}System.out.println("無鎖計算耗時: " + average(elapsedTime4NoLock) + "ms");System.out.println("synchronized計算耗時: " + average(elapsedTime4Synchronized) + "ms");System.out.println("ReentrantLock計算耗時: " + average(elapsedTime4ReentrantLock) + "ms");System.out.println("cas計算耗時: " + average(elapsedTime4Cas) + "ms");}/*** synchronized加鎖*/private synchronized long addWithSynchronized(long i) {i = i + 1;return i;}/*** ReentrantLock加鎖*/private long addWithReentrantLock(long i, Lock lock) {lock.lock();i = i + 1;lock.unlock();return i;}/*** 計算平均耗時*/private double average(Collection<Long> collection) {return collection.stream().mapToLong(i -> i).average().orElse(0);} }

從案例中我們可能看出在單線程環境場景下cas的性能要高于鎖相關的操作。當然,在競爭比較激烈的情況下性能可能會有所下降,因為要不斷的重試和回退或者放棄操作,這也是CAS的一個缺點所在,因為這些重試,回退等操作通常用開發者來實現。

CAS的實現并非是簡單的代碼層面控制的,而是需要硬件的支持,因此在不同的體系架構之間執行的性能差異很大。但是一個很管用的經驗法則是:在大多數處理器上,在無競爭的鎖獲取和釋放的”快速代碼路徑“上的開銷,大約是CAS開銷的兩倍。

為何CAS如此優秀

硬件加持,現代大多數處理器都從硬件層面通過一些列指令實現CompareAndSwap(比較并交換)同步原語,進而使操作系統和JVM可以直接使用這些指令實現鎖和并發的數據結構。我們可以簡單認為,CAS是將比較和交換合成是一個原子操作

JVM對CAS的支持, 由于Java程序運行在JVM上,所以應對不同的硬件體系架構的處理則需要JVM來實現。在不支持CAS操作的硬件上,jvm將使用自旋鎖來實現。

CAS的ABA問題

cas操作讓我們減少了鎖帶來的性能損耗,同時也給我們帶來了新的麻煩-ABA問題。

在線程A讀取到x的值與執行CAS操作期間,線程B對x執行了兩次修改,x的值從100變成200,然后再從200變回100;而后在線程A執行CAS操作過程中并未發現x發生過變化,成功修改了x的值。由于x的值100 ->200->100,所以稱之為ABA的原因。

魔高一尺道高一丈,解決ABA的問題目前最常用的辦法就是給數據加上“版本號”,每次修改數據時同時改變版本號即可。

Q&A

在競爭比較激烈的情況下,CAS要進行回退,重試等操作才能得到正確的結果,那么CAS一定比加鎖性能要高嗎?

有道無術,術可成;有術無道,止于術

歡迎大家關注Java之道公眾號

好文章,我在看??

總結

以上是生活随笔為你收集整理的无锁并发的CAS为何如此优秀?的全部內容,希望文章能夠幫你解決所遇到的問題。

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