日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

為什么Java volatile++不是原子性的詳解

瀏覽:18日期:2022-08-17 13:36:22
問題

在討論原子性操作時,我們經常會聽到一個說法:任意單個volatile變量的讀寫具有原子性,但是volatile++這種操作除外。

所以問題就是:為什么volatile++不是原子性的?

答案

因為它實際上是三個操作組成的一個符合操作。

首先獲取volatile變量的值 將該變量的值加1 將該volatile變量的值寫會到對應的主存地址

一個很簡單的例子:

如果兩個線程在volatile讀階段都拿到的是a=1,那么后續在線程對應的CPU核心上進行自增當然都得到的是a=2,最后兩個寫操作不管怎么保證原子性,結果最終都是a=2。每個操作本身都沒啥問題,但是合在一起,從整體上看就是一個線程不安全的操作:發生了兩次自增操作,然而最終結果卻不是3。

分析

結合內存屏障這個概念對volatile的讀寫操作深入理解的話:

第一步:讀

在第一步操作的指令后,會增加兩個內存屏障:

在Volatile讀操作后插入LoadLoad屏障,防止前面的Volatile讀與后面的普通讀重排序 在Volatile讀操作后插入LoadStore屏障,防止前面的Volatile讀與后面的普通寫重排序

因此第一個指令和它后續的普通讀寫操作會被保證沒有重排序來搗亂。通常是去內存中去讀。

那么問題又來了,為什么通常去內存中讀?

其實這個問題要說細的話可以很細,大概就兩個關鍵點吧:

volatile的寫操作的緩存失效機制 最后一個對volatile變量執行寫操作的CPU,由于在它對應的緩存中保有最新的值,因此可以不用再去主存里面獲取

具體看下面第三步的分析。

第二步:自增

這個步驟沒什么特別的,就是在CPU自身的高速緩存(寄存器,L1-L3 Cache)中完成。不涉及到緩存和內存的交互。

第三步:寫

volatile寫算是一個重點。

根據JMM對于volatile變量類型的語義規范:volatile在編譯之后,會在變量寫操作時添加LOCK前綴指令。這個LOCK前綴指令在多核處理器的環境中,有這樣的作用:

通知CPU將當前處理器緩存行的數據寫回到系統主存中 該寫回操作將使其他CPU緩存了該內存地址的數據無效

另外,內存屏障在volatile的寫操作中起到了很大的作用,來保證上面兩點能夠實現:

在Volatile寫操作前插入StoreStore屏障,防止前面其他寫與本次Volatile寫重排序 在Volatile寫操作后插入StoreLoad屏障,防止本次的Volatile寫與后面的讀操作重排序 延伸

那么為了解決volatile++這類復合操作的原子性,有什么方案呢?其實方案也比較多的,這里提供兩種典型的:

使用synchronized關鍵字 使用AtomicInteger/AtomicLong原子類型

synchronized關鍵字

synchronized是比較原始的同步手段。它本質上是一個獨占的,可重入的鎖。當一個線程嘗試獲取它的時候,可能會被阻塞住,所以高并發的場景下性能存在一些問題。

在某些場景下,使用synchronized關鍵字和volatile是等價的:

寫入變量值時候不依賴變量的當前值,或者能夠保證只有一個線程修改變量值。 寫入的變量值不依賴其他變量的參與。 讀取變量值時候不能因為其他原因進行加鎖。

加鎖可以同時保證可見性和原子性,而volatile只保證變量值的可見性。

AtomicInteger/AtomicLong

這類原子類型比鎖更加輕巧,比如AtomicInteger/AtomicLong分別就代表了整型變量和長整型變量。

在它們的實現中,實際上分別使用的volatile int/volatile long保存了真正的值。因此,也是通過volatile來保證對于單個變量的讀寫原子性的。

在此基礎之上,它們提供了原子性的自增自減操作。比如incrementAndGet方法,這類方法相對于synchronized的好處是:它們不會導致線程的掛起和重新調度,因為在其內部使用的是CAS非阻塞算法。

CAS是什么

所謂的CAS全程為CompareAndSet。直譯過來就是比較并設置。這個操作需要接受三個參數:

內存位置 舊的預期值 新值

這個操作的做法就是看指定內存位置的值符不符合舊的預期值,如果符合的話就將它替換成新值。它對應的是處理器提供的一個原子性指令 - CMPXCHG。

比如AtomicLong的自增操作:

public final long incrementAndGet() { for (;;) { long current = get(); // Step 1 long next = current + 1; // Step 2 if (compareAndSet(current, next)) // Step 3 return next; }}public final boolean compareAndSet(long expect, long update) { return unsafe.compareAndSwapLong(this, valueOffset, expect, update);}

我們考慮兩個線程T1和T2,同時執行到了上述Step 1處,都拿到了current值為1。然后通過Step 2之后,current在兩個線程中都被設置為2。

緊接著,來到Step 3。假設線程T1先執行,此時符合CompareAndSet的設置規則,因此內存位置對應的值被設置成2,線程T1設置成功。當線程T2執行的時候,由于它預期current為1,但是實際上已經變成了2,所以CompareAndSet執行不成功,進入到下一輪的for循環中,此時拿到最新的current值為2,如果沒有其它線程感染的話,再次執行CompareAndSet的時候就能夠通過,current值被更新為3。

所以不難發現,CAS的工作主要依賴于兩點:

無限循環,需要消耗部分CPU性能 CPU原子指令CompareAndSet

雖然它需要耗費一定的CPU Cycle,但是相比鎖而言還是有其優勢,比如它能夠避免線程阻塞引起的上下文切換和調度。這兩類操作的量級明顯是不一樣的,CAS更輕量一些。

總結

我們說對于volatile變量的讀/寫操作是原子性的。因為從內存屏障的角度來看,對volatile變量的單純讀寫操作確實沒有任何疑問。

由于其中摻雜了一個自增的CPU內部操作,就造成這個復合操作不再保有原子性。

然后,討論了如何保證volatile++這類操作的原子性,比如使用synchronized或者AtomicInteger/AtomicLong原子類。

到此這篇關于為什么Java volatile++不是原子性的文章就介紹到這了,更多相關Java volatile++不是原子性內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Java
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
国产一区精品福利| 视频一区二区三区入口| 日韩不卡免费高清视频| 国产三级精品三级在线观看国产| 久久人人88| 99精品在线观看| 欧美日本不卡| 亚洲天堂av资源在线观看| 精品国产麻豆| 岛国av免费在线观看| 国产福利一区二区精品秒拍 | 亚洲欧洲一区| 91看片一区| 久久伊人亚洲| 久久精品国产免费| 国产日韩欧美三区| 日韩国产一二三区| 91欧美精品| 日本va欧美va精品| 视频一区视频二区中文字幕| 视频一区在线播放| 亚洲欧美日韩专区| 日韩视频一区二区三区在线播放免费观看| 三级精品视频| 国产一区二区精品福利地址| 国产情侣久久| 免费在线观看一区二区三区| 国产精品va| 久久影视三级福利片| 精精国产xxxx视频在线野外| 国产亚洲电影| 亚洲另类黄色| 综合亚洲视频| 亚洲毛片网站| 国产真实久久| 91久久国产| 亚洲精品少妇| 日本午夜精品视频在线观看| 日本成人在线一区| 精品视频高潮| 国产精品蜜芽在线观看| av资源中文在线| 欧美极品中文字幕| 午夜av成人| 欧美午夜不卡| 日韩中文字幕91| 美女久久久久久 | 久久激情av| 99视频一区| 久久国产电影| 免费看久久久| 鲁鲁在线中文| 国内精品亚洲| 亚洲一二三区视频| 蜜桃久久久久久| 日韩成人午夜精品| 美国三级日本三级久久99| 国产精久久久| 精品久久中文| 黄色国产精品| 日韩电影免费网址| 日本蜜桃在线观看视频| 国产欧美三级| 日韩中文字幕无砖| 91麻豆精品激情在线观看最新| 国产成人1区| 久久wwww| 国产精品人人爽人人做我的可爱| 日韩国产91| 99久久99久久精品国产片果冰| 亚洲精品少妇| 老鸭窝毛片一区二区三区| 性欧美xxxx免费岛国不卡电影| 一区二区国产在线| 免费视频一区二区| 男女性色大片免费观看一区二区 | 国产精品国码视频| 欧美亚洲人成在线| 麻豆国产91在线播放| 欧美日韩一区自拍| 国产精品资源| 日本成人中文字幕在线视频| 日韩精品免费视频人成| 日韩精品91亚洲二区在线观看| 视频一区二区中文字幕| 亚洲精品精选| 久久精品高清| 伊人精品一区| 国户精品久久久久久久久久久不卡| 国产精品一区二区三区美女| 久色成人在线| 亚洲精品日韩久久| 91亚洲精品在看在线观看高清| 国产图片一区| 精品久久免费| 在线看片国产福利你懂的| 精品久久亚洲| 欧美精选一区二区三区| 精品视频91| 久久在线电影| 日韩影片在线观看| 精品免费av一区二区三区| 亚洲a在线视频| 日本一区二区三区中文字幕| 国产精品www.| 久久久天天操| 中文字幕亚洲在线观看| 999久久久免费精品国产| 91成人精品在线| 夜鲁夜鲁夜鲁视频在线播放| 三级在线看中文字幕完整版| 亚洲毛片在线| 日本不良网站在线观看| 一区二区电影| 久热综合在线亚洲精品| 久久中文字幕一区二区三区| 韩国精品主播一区二区在线观看| 在线亚洲免费| 99久久99视频只有精品| 蜜桃一区二区三区在线观看 | 久久电影tv| 亚洲自拍另类| 国产亚洲精品自拍| 视频在线不卡免费观看| 亚洲欧美一级| 国产欧美一区二区三区精品观看| 国产一区二区亚洲| 黄色欧美日韩| 欧美激情在线精品一区二区三区| 88久久精品| 波多野结衣一区| 最新日韩av| 男人天堂欧美日韩| 一区二区亚洲视频| 国产精品地址| 日韩精品一区二区三区中文在线| 午夜日本精品| 六月婷婷综合| 日韩欧美一区二区三区免费看| 91综合久久爱com| 国产伦精品一区二区三区视频| 精品美女在线视频| 日韩欧美一区二区三区在线视频| 欧美 日韩 国产精品免费观看| 色吊丝一区二区| 免费看日韩精品| 国产成人久久精品一区二区三区| 欧美精品一二| 久久久水蜜桃av免费网站| 国产真实久久| 美女性感视频久久| 91精品国产经典在线观看| 日韩av网站免费在线| 国产欧美日韩亚洲一区二区三区| 综合激情在线| 国产成年精品| 蜜臀av性久久久久蜜臀aⅴ流畅| 丝袜亚洲另类欧美| 午夜久久一区| 91精品国产经典在线观看| 日本h片久久| 国产成人在线中文字幕| 一区二区自拍| 久久免费视频66| 日韩中文字幕1| 成人黄色av| 亚洲精品九九| 久久久天天操| 欧美亚洲人成在线| 久久亚洲国产| 欧美a在线观看| 日韩午夜免费| 欧美一区免费| 99视频在线精品国自产拍免费观看| 日本aⅴ免费视频一区二区三区| 亚洲综合电影| 国产精品一区2区3区| 亚洲欧美不卡| 性欧美xxxx免费岛国不卡电影| 国产情侣久久| 午夜视频一区二区在线观看| 欧美成a人国产精品高清乱码在线观看片在线观看久| 亚洲精品小说| 久久婷婷亚洲| 国内精品亚洲| 精品国产一区二区三区av片| 亚洲精品免费观看| 日韩精品免费一区二区三区| 日韩动漫一区| 91精品视频一区二区| 亚洲免费成人av在线| 黄色成人在线网址| 久久伦理在线| 欧美+日本+国产+在线a∨观看| 国产精品不卡| 国产精品伦理久久久久久| 久久99国产精品视频| 国产精品亚洲欧美| 国产激情一区| 久久精品一区二区三区中文字幕|