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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Volatile 关键字 内存可见性

發(fā)布時間:2025/5/22 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Volatile 关键字 内存可见性 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

?

1、問題引入

實現(xiàn)線程:

public class ThreadDemo implements Runnable {private boolean flag = false;@Overridepublic void run(){flag = true;System.out.println("flag=" + flag);}public boolean isFlag(){return flag;}public void setFlag(boolean flag){this.flag = flag;} }

測試類:

public class VolatileTest {public static void main(String[] args){ThreadDemo threadDemo = new ThreadDemo();new Thread(threadDemo).start();while (true){if(threadDemo.isFlag()){System.out.println("----------------");break;}}} }

結(jié)果:flag=true,并且程序不會停止

結(jié)果分析從結(jié)果中看到,線程threadDemo 將 flag 被修改為 ture 了,但是 while 循環(huán)中的 if 判斷中沒有進(jìn)入(即 flag = false);主線程中的flag和threadDemo 中的flag值不一樣。

內(nèi)存可見性的問題:多個線程操作共享數(shù)據(jù)時,各個線程之間的數(shù)據(jù)不一致;

  JVM會為每個線程分配一個獨立的緩存用于提高效率。

(1)程序開始運行時主存中的flag=false;

(2)接著線程threadDemo會修改flag數(shù)據(jù):threadDemo先從主存中獲取到flag數(shù)據(jù)(false),然后在線程threadDemo中的緩存數(shù)據(jù)修改為true;

(3)在這個時候main線程來了,main線程從主存中讀取到的flag=false;

(4)線程threadDemo將flag=true寫入到主存中;

(5)while(true) 的執(zhí)行效率特別高,以至于 main 線程沒有機會從主存中讀取數(shù)據(jù);

解決內(nèi)存可見性的問題

1、增加同步鎖,用?synchronized 進(jìn)行同步,代碼如下:

public class VolatileTest {public static void main(String[] args){ThreadDemo threadDemo = new ThreadDemo();new Thread(threadDemo).start();while (true){synchronized (threadDemo){if (threadDemo.isFlag()){System.out.println("----------------");break;}}}} }

以上代碼存在的問題:增加同步鎖解決了內(nèi)存可見性的問題,但是效率特別低;

2、增加 volatile 關(guān)鍵字,修飾線程的共享數(shù)據(jù),代碼如下:

public class ThreadDemo implements Runnable {private volatile boolean flag = false;@Overridepublic void run(){flag = true;System.out.println("flag=" + flag);}public boolean isFlag(){return flag;}public void setFlag(boolean flag){this.flag = flag;} }

?

?Volatile關(guān)鍵字不具備“互斥性”,Volatile不能保證“原子性”;

Java內(nèi)存模型(Java Memory Model)描述了Java程序中各種變量(線程共享變量)的訪問規(guī)則,以及在JVM中將變量存儲到內(nèi)存和從內(nèi)存中讀取出變量這樣的底層細(xì)節(jié)。
??? 所有的變量都存儲在主內(nèi)存中。每個線程都有自己獨立的工作內(nèi)存,里面保存該線程使用到的變量的副本(主內(nèi)存中該變量的一份拷貝),如圖

兩條規(guī)定:

  • 線程對共享變量的所有操作都必須在自己的工作內(nèi)存中進(jìn)行,不能直接從主內(nèi)存中讀取
  • 不同線程之間無法直接訪問其他線程工作內(nèi)存中的變量,線程間變量值的傳遞需要通過主內(nèi)存來完成。

在這種模型下會存在一個現(xiàn)象,即緩存中的數(shù)據(jù)與主內(nèi)存的數(shù)據(jù)并不是實時同步的,各CPU(或CPU核心)間緩存的數(shù)據(jù)也不是實時同步的。這導(dǎo)致在同一個時間點,各CPU所看到同一內(nèi)存地址的數(shù)據(jù)的值可能是不一致。

?

volatile關(guān)鍵字
  能夠保證volatile變量的可見性,不能保證volatile變量復(fù)合操作的原子

volatile如何實現(xiàn)內(nèi)存的可見性:

深入來說:通過加入內(nèi)存屏障和禁止重排序優(yōu)化來實現(xiàn)的
  在每個volatile寫操作前插入StoreStore屏障,在寫操作后插入StoreLoad屏障;
  在每個volatile讀操作前插入LoadLoad屏障,在讀操作后插入LoadStore屏障;

通俗地講:volatile變量在每次被線程訪問時,都強迫從主內(nèi)存中重讀該變量的值,而當(dāng)該變量發(fā)生變化時,又會強迫將最新的值刷新到主內(nèi)存。這樣任何時刻,不同的線程總能看到該變量的最新值。

線程volatile變量的過程:
(1)改變線程工作內(nèi)存中volatile變量副本的值
(2)將改變后的副本的值從工作內(nèi)存刷新到主內(nèi)存

線程volatile變量的過程:
(2)從主內(nèi)存中讀取volatile變量的最新值到線程的工作內(nèi)存中
(2)從工作內(nèi)存中讀取volatile變量的副本

?

?參考鏈接:

https://www.cnblogs.com/amei0/p/8378625.html

?

轉(zhuǎn)載于:https://www.cnblogs.com/yufeng218/p/10116595.html

總結(jié)

以上是生活随笔為你收集整理的Volatile 关键字 内存可见性的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。