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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

高并发之CAS机制和ABA问题

發布時間:2025/7/14 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 高并发之CAS机制和ABA问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

什么是CAS機制

CAS是英文單詞Compare and Swap的縮寫,翻譯過來就是比較并替換

CAS機制中使用了3個基本操作數:內存地址V,舊的預期值A,要修改的新值B。

看如下幾個例子:

package com.example.demo.concurrentDemo;import org.junit.Test;import java.util.concurrent.atomic.AtomicInteger;public class CasTest {private static int count = 0;@Testpublic void test1(){for (int j = 0; j < 2; j++) {new Thread(() -> {for (int i = 0; i < 10000; i++) {count++;}}).start();}try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}//結果必定 count <= 20000 System.out.println(count);}@Testpublic void test2() {for (int j = 0; j < 2; j++) {new Thread(() -> {for (int i = 0; i < 10000; i++) {synchronized (this) {count++;}}}).start();}try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}//synchronized 類似于悲觀鎖//synchronized關鍵字會讓沒有得到鎖資源的線程進入BLOCKED狀態,而后在爭奪到鎖資源后恢復為RUNNABLE狀態//這個過程中涉及到操作系統用戶模式和內核模式的轉換,代價比較高 System.out.println(count);}private static AtomicInteger atoCount = new AtomicInteger(0);@Testpublic void test3() {for (int j = 0; j < 2; j++) {new Thread(() -> {for (int i = 0; i < 10000; i++) {atoCount.incrementAndGet();}}).start();}try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}//Atomic操作類的底層正是用到了“CAS機制” System.out.println(atoCount);}}

CAS 缺點

1) CPU開銷過大

在并發量比較高的情況下,如果許多線程反復嘗試更新某一個變量,卻又一直更新不成功,循環往復,會給CPU帶來很到的壓力。

這個可以通過看:AtomicInteger.incrementAndGet()源碼,可知這是一個無限循環,獲取實際值與預期值比較,當相等才會跳出循壞。

2) 不能保證代碼塊的原子性

CAS機制所保證的知識一個變量的原子性操作,而不能保證整個代碼塊的原子性。比如需要保證3個變量共同進行原子性的更新,就不得不使用synchronized了。

3) ABA問題

這是CAS機制最大的問題所在。

?

什么是ABA?先看下面例子:

我們先來看一個多線程的運行場景:
時間點1 :線程1查詢值是否為A?
時間點2 :線程2查詢值是否為A?
時間點3 :線程2比較并更新值為B?
時間點4 :線程2查詢值是否為B?
時間點5 :線程2比較并更新值為A?
時間點6 :線程1比較并更新值為C

在這個線程執行場景中,2個線程交替執行。線程1在時間點6的時候依然能夠正常的進行CAS操作,盡管在時間點2到時間點6期間已經發生一些意想不到的變化, 但是線程1對這些變化卻一無所知,因為對線程1來說A的確還在。通常將這類現象稱為ABA問題。
ABA發生了,但線程不知道。又或者鏈表的頭在變化了兩次后恢復了原值,但是不代表鏈表就沒有變化。

ABA隱患

就像兵法講的:偷梁換柱、李代桃僵?

歷史事件:趙氏孤兒

?解決ABA問題兩種方法:

1、悲觀鎖思路,加鎖;

2、樂觀鎖思路,通過AtomicStampedReference.class?

源碼實現,具體看源碼:

1. 創建一個Pair類來記錄對象引用和時間戳信息,采用int作為時間戳,實際使用的時候時間戳信息要做成自增的,否則時間戳如果重復,還會出現ABA的問題。這個Pair對象是不可變對象,所有的屬性都是final的, of方法每次返回一個新的不可變對象。

2. 使用一個volatile類型的引用指向當前的Pair對象,一旦volatile引用發生變化,變化對所有線程可見。

3. set方法時,當要設置的對象和當前Pair對象不一樣時,新建一個不可變的Pair對象。

4. compareAndSet方法中,只有期望對象的引用和版本號和目標對象的引用和版本好都一樣時,才會新建一個Pair對象,然后用新建的Pair對象和原理的Pair對象做CAS操作。

5.?實際的CAS操作比較的是當前的pair對象和新建的pair對象,pair對象封裝了引用和時間戳信息。

Demo:

?

@Testpublic void test4() {final int timeStamp = atoReferenceCount.getStamp();new Thread(() -> {while(true){if(atoReferenceCount.compareAndSet(atoReferenceCount.getReference(),atoReferenceCount.getReference()+1, timeStamp, timeStamp + 1)){System.out.println("11111111");break;}}},"線程1:").start();new Thread(() -> {while(true){if(atoReferenceCount.compareAndSet(atoReferenceCount.getReference(),atoReferenceCount.getReference()+1, timeStamp, timeStamp + 1)){System.out.println("2222222");break;}}},"線程2:").start();try {Thread.sleep(10000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(atoReferenceCount.getReference());}

第二個沒有執行,因為時間戳不對了。

修改下代碼:

@Testpublic void test4() {for (int i = 0; i < 10; i++) {new Thread(() -> {boolean f = atoReferenceCount.compareAndSet(atoReferenceCount.getReference(),atoReferenceCount.getReference() + 1, atoReferenceCount.getStamp(),atoReferenceCount.getStamp() + 1);System.out.println("線程"+Thread.currentThread()+"result="+f);}, "線程:"+i).start();}try {Thread.sleep(10000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(atoReferenceCount.getReference());}

結果:可見線程:0,比較的時候發現時間戳變了,所以沒有+1。

demo2:

@Testpublic void test5() {for (int i = 0; i < 4; i++) {new Thread(() -> {for (int j = 0; j < 500; j++) {boolean f = atoReferenceCount.compareAndSet(atoReferenceCount.getReference(),atoReferenceCount.getReference() + 1, atoReferenceCount.getStamp(),atoReferenceCount.getStamp() + 1);System.out.println("線程"+Thread.currentThread()+">>j="+j+",result="+f);}}, "線程:"+i).start();}try {Thread.sleep(10000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(atoReferenceCount.getReference());}

?有3次比較時間戳發現已經不同

?

參考:

https://blog.csdn.net/qq_32998153/article/details/79529704

轉載于:https://www.cnblogs.com/xiaozhuanfeng/p/10846180.html

總結

以上是生活随笔為你收集整理的高并发之CAS机制和ABA问题的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 日本黄色大片视频 | 国产一级片久久 | 亚洲免费精品视频 | 熟女丰满老熟女熟妇 | 中国久久 | 日本不卡一区二区三区 | 岛国av免费观看 | 正在播放超嫩在线播放 | 三级影片在线免费观看 | 性高潮影院 | 欧美在线免费视频 | 男女男精品网站 | 国产一区av在线 | 中国三级视频 | www久久99 | 青青草精品在线 | 国产永久精品 | 污色视频 | 都市激情亚洲色图 | 亚洲女人av | 人妻丝袜一区二区三区 | 久久亚洲私人国产精品va | 日韩美女久久 | 久热久| 精品一区国产 | 国产精品成人在线 | 国产精品久久久久久妇女 | 91手机在线观看 | 欧美成人精品欧美一级乱黄 | 欧美专区一区 | 爱爱视频网址 | 午夜激情福利在线 | 亚洲激情综合网 | 青娱乐毛片| 中文字幕另类 | 国产精品自拍视频一区 | 岛国av网址 | 被绑在床强摁做开腿呻吟 | 亚洲一区二区视频在线 | 午夜影视剧场 | 国产精品.www | 国产视频最新 | 日韩欧美一二区 | 日韩精品一区二区三区电影 | 精品一区二区久久 | 日韩欧美国产成人精品免费 | 国产精品美女www爽爽爽 | 日本成人社区 | 日韩欧美国产亚洲 | 51吃瓜网今日 | 日皮视频免费看 | 激情天堂网 | 91超碰在线免费观看 | 99re热在线视频 | 国产乱叫456在线 | jizzjizzjizz亚洲| 国产呻吟av | av动漫免费看| 91欧美亚洲 | 中文字幕乱视频 | 97午夜| 伊人久久大香线蕉av色婷婷色 | 国产一线天粉嫩馒头极品av | 欧美一区二区三区啪啪 | 欧美成年人| 97欧美视频 | 国产精品区一区二区三 | 色倩网站 | 日本人添下边视频免费 | 久久久久久一区 | 伦在线| 欧美日韩一区二区三区在线电影 | 天天色影院 | 久久免费成人 | 亚洲高清av在线 | 青娱乐激情 | 日韩欧美成人一区二区三区 | 国产第三页 | av网站网址| 天堂资源地址在线 | 无码国精品一区二区免费蜜桃 | 18禁超污无遮挡无码免费游戏 | 奇米影视中文字幕 | 久久久av网站 | 一个综合色 | 口舌奴vk | 欧美性生活一区二区三区 | 国产欧美日韩综合精品一区二区 | 精品人妻无码一区二区三区蜜桃一 | 日韩美女爱爱 | 亚洲日本不卡 | 精品亚洲乱码一区二区 | av在线资源播放 | 日本熟妇色xxxxx日本免费看 | www.国产黄色 | 中文字幕在线观看网 | 亚洲天堂第一 | 亚洲人精品 | 青青草原综合久久大伊人精品 |