Volatile可見性和原子性

      網(wǎng)友投稿 619 2025-03-31

      1.Volatile簡介


      Volatile是Java虛擬機提供的輕量級的同步機制。

      1.1 Volatile理解

      volatile變量是Java語言提供的一種的同步機制,即用來確保變量的變更的操作時通知到其他的線程。當使用volatile關(guān)鍵字修飾變量的時候,編譯期以及運行期都會注意到這個變量是共享的,因此不會將這個變量上的操作與其他內(nèi)存操作一起重新排序。

      并且volatile關(guān)鍵字修飾的變量不會被緩存進入寄存器或者其他處理器不可見的地方,在讀取volatile關(guān)鍵字修飾的變量時總會返回最新寫入的值。

      1.2 Volatile的可見性和原子性

      1.2.1 保證可見性

      如上面代碼中,如果不加volatile關(guān)鍵字,當前線程無法感知主線程中的num的變化,當主線程中tem變量已經(jīng)變?yōu)?的時候,線程A中的tem變量并沒有發(fā)現(xiàn)tem已經(jīng)發(fā)生了變化,會繼續(xù)執(zhí)行while中的循環(huán),一直一直循環(huán)下去。。。但是當加了volatile關(guān)鍵詞后,tem變量就會對線程A保證了可見性,當發(fā)現(xiàn)tem變量發(fā)生變化不為0后,就自動跳出循環(huán)結(jié)束執(zhí)行任務。

      private volatile static int tem = 0; public static void main(String[] args) throws InterruptedException { new Thread(()->{ while (tem == 0){ // System.out.println("變量num==0,執(zhí)行"+Thread.currentThread().getName()); } },"線程A").start(); TimeUnit.SECONDS.sleep(1); tem = 1; System.out.println(tem); }

      注:while循環(huán)中不能加println打印方法,因為println方法是加鎖的,有同步代碼塊會保證變量修改的可見性,在變量num修改后會立刻刷回到主存中,因此要測試就不能加打印語句。

      public void println(String x) { synchronized (this) { print(x); newLine(); } }

      1.2.2 不保證原子性

      1.2.2.1 不保證原子性的小案例

      原子性是表示不可分割,執(zhí)行任務的時候不能被打擾,要么同事成功要么同時失敗。

      注:yieled()是禮讓方法,是讓當前線程讓出給其他線程來執(zhí)行,由于java語言中有兩個線程是默認執(zhí)行的,一個是main線程,一個是gc線程,由于Thread.yieled()方法是在主線程中執(zhí)行的,只要有其它線程存在,就讓main線程和gc線程讓出cpu給其他線程,這樣main線程就不會執(zhí)行下去,而是禮讓后讓其他線程執(zhí)行,等其他線程執(zhí)行完了后再執(zhí)行。

      Volatile可見性和原子性

      private static int tem = 0; public static void add(){ tem++; } public static void main(String[] args) { for (int i = 1; i <= 20; i++) { new Thread(()->{ for (int j = 0; j < 100; j++) { add(); // System.out.println("for循環(huán)中"+Thread.currentThread().getName()); } },"線程"+i).start(); } while (Thread.activeCount() > 2){ Thread.yield(); } System.out.println(Thread.currentThread().getName()+ " "+ tem); }

      打印結(jié)果為:main 1990

      可以看出在不做任何處理的情況下多線程自由執(zhí)行的結(jié)果不為20*100=2000;

      1.2.2.2 案例源碼探析

      為什么會出現(xiàn)結(jié)果不同的情況?

      因為add()方法中只有一行自增的執(zhí)行語句,我們可以通過javap反編譯一下成字節(jié)碼文件,可以看出add()方法實際上會有有四步:

      1.2.2.2.1 獲取靜態(tài)變量,或得值

      1.2.2.2.2 常量不用管

      1.2.2.2.3 自增,+1的操作

      1.2.2.2.4 返回改變后的變量,寫回這個變量的值

      根據(jù)分析我們可以得出num++;這一行自增代碼并不是原子性操作,而是分為很多步執(zhí)行的,所以多線程的情況下會受到影響。而之所以會比理論值小的結(jié)果是因為線程回寫數(shù)據(jù)到主存中,覆蓋了其他更快執(zhí)行的結(jié)果導致的。

      1.2.2.3 那么如何保證結(jié)果為我們想要的2000呢?(如何保證原子性)

      1.2.2.3.1 可以通過加synchronized關(guān)鍵字或者加lock鎖

      1.2.2.3.2 使用juc中的原子類來處理(推薦)

      由于synchronized關(guān)鍵字或者加lock鎖解決更耗費資源,所以我們找到了一種給省資源的方式就是使用juc中的原子類來處理。底層是通過CAS來處理的(直接和操作系統(tǒng)掛鉤,在內(nèi)存中修改值),有很高的的效率。

      volatitle和AtomicInteger需要同時使用,不一起使用的話,多運行幾次會出現(xiàn)可見性會體現(xiàn)不出來的情況;

      // private volatile static int tem = 0; private volatile static AtomicInteger tem = new AtomicInteger(); public static void add(){ // tem++; tem.getAndIncrement(); } public static void main(String[] args) { for (int i = 1; i <= 20; i++) { new Thread(()->{ for (int j = 0; j < 100; j++) { add(); } }).start(); } while (Thread.activeCount() > 2){ Thread.yield(); } System.out.println(Thread.currentThread().getName()+ " "+ tem); }

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔相應法律責任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔相應法律責任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:甘特圖協(xié)同
      下一篇:白酒制造業(yè)清潔生產(chǎn)管理制度(白酒制造業(yè)清潔生產(chǎn)標準)
      相關(guān)文章
      久久亚洲中文字幕精品一区| 久久亚洲国产欧洲精品一| 亚洲日韩精品一区二区三区| 亚洲喷奶水中文字幕电影| 亚洲精品无码永久在线观看| 亚洲国产精品无码久久| 亚洲入口无毒网址你懂的| 亚洲av日韩av天堂影片精品| 亚洲乱码一区二区三区在线观看| 亚洲国产成人久久笫一页| 亚洲人成自拍网站在线观看| 亚洲国产美女视频| 亚洲精品偷拍无码不卡av| 亚洲电影一区二区| 亚洲s色大片在线观看| 亚洲无线码在线一区观看| 亚洲精品A在线观看| 最新国产精品亚洲| 亚洲精品亚洲人成在线观看麻豆| 亚洲AV无码欧洲AV无码网站| 国产亚洲精品欧洲在线观看| 亚洲xxxx视频| 朝桐光亚洲专区在线中文字幕| 亚洲国产精品嫩草影院在线观看 | 另类专区另类专区亚洲| 亚洲色欲色欱wwW在线| 亚洲人和日本人jizz| 亚洲人成www在线播放| 亚洲AV无码乱码麻豆精品国产| 激情综合亚洲色婷婷五月APP| 自拍偷区亚洲国内自拍| 亚洲精品宾馆在线精品酒店| 亚洲AV成人无码网站| 亚洲国产综合久久天堂| 亚洲精品无码久久久久| 亚洲视频在线观看| 亚洲国产理论片在线播放| 亚洲丝袜中文字幕| 亚洲日本中文字幕天天更新| 亚洲日韩精品无码专区网站| 亚洲人AV永久一区二区三区久久|