日韩性视频-久久久蜜桃-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问题的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 一级黄色短片 | 国产在线观看免费视频今夜 | 丁香色综合 | 欧美深夜福利 | 优优色影院 | 国产精品乱码久久久 | 日韩一级在线观看 | 大乳巨大乳j奶hd | 成av人在线观看 | a视频在线看 | 99久久精品久久久久久清纯 | 69人妻精品久久无人专区 | 日韩国产精品一区二区三区 | 一级性爱视频 | 久久精品无码Av中文字幕 | 亚洲系列| 啪一啪在线 | 国产人妻精品一区二区三区 | 欧美大浪妇猛交饥渴大叫 | 欧美黑人一级片 | 88国产精品 | 亚洲天堂手机在线 | 午夜精品久久久久久久久久蜜桃 | 色眯眯网 | 免费看毛片网站 | 日韩av二区| 欧美一区二区黄片 | 黄色www| 国产精品自产拍高潮在线观看 | 毛片网站免费 | 人人插人人干 | 色播99| 三级视频久久 | 黄在线免费| 级毛片内射视频 | 国产影视一区二区三区 | 亚洲第一女人av | 亚洲精品粉嫩小泬 | 日韩有码一区二区三区 | 去毛片| 日韩午夜在线视频 | 少妇3p视频 | 一级片日韩 | 亚洲丁香 | a级黄视频 | 天天碰天天摸 | 精品人妻码一区二区三区红楼视频 | 婷婷激情小说网 | 影音先锋激情 | 欧美××××黑人××性爽 | 国产女人18毛片水真多 | 日韩色区 | 国产在线视频一区二区三区 | 久久国产毛片 | 你懂的av在线 | 四虎成人精品 | 日韩成人福利视频 | 欧美 国产 综合 | 欧美全黄| 久久这里只有 | 九久久久久 | 在线观看污污网站 | 久久成年网| 中文字幕免费高清在线观看 | 久操成人| 成人黄色大片 | 日本精品视频在线 | 国产在线观看免费播放 | 欧美黑吊大战白妞 | 亚洲爱爱av | 中国挤奶哺乳午夜片 | 午夜精品一区二区三 | 日韩操操 | 成年人免费在线视频 | 91最新地址永久入口 | 污视频免费网站 | 中文不卡av| 大尺度床戏视频 | 91成人毛片| 欧美视频三区 | 欧美91av| www.成人国产 | 少妇25p | 美脚の诱脚舐め脚视频播放 | 日韩网站在线播放 | 桃色91| 久久久久久av无码免费看大片 | 美女视频黄色免费 | 曰批免费视频播放免费 | 欧洲av一区二区 | 欧美日韩人妻精品一区在线 | 中文字幕av免费观看 | 三级网站国产 | 自拍偷在线精品自拍偷无码专区 | 国产美女久久 | 国产一区精品无码 | 久久久77 | 日韩不卡视频一区二区 | 欧美精品福利视频 |