一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - java高并發(fā)的volatile與Java內存模型詳解

java高并發(fā)的volatile與Java內存模型詳解

2022-03-02 00:48路人甲Java Java教程

這篇文章主要介紹了java高并發(fā)的volatile與Java內存模型,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Demo09 {  
    public static boolean flag = true
    public static class T1 extends Thread {
        public T1(String name) {   
            super(name);   
        }  
        @Override  
        public void run() {
            System.out.println("線程" + this.getName() + " in"); 
            while (flag) { 
                ;  
            }  
            System.out.println("線程" + this.getName() + "停止了"); 
        }  
    }  
    public static void main(String[] args) throws InterruptedException {   
        new T1("t1").start();  
        //休眠1秒 
        Thread.sleep(1000);
        //將flag置為false 
        flag = false;  
    }  
}

運行上面代碼,會發(fā)現(xiàn)程序無法終止。

線程t1的run()方法中有個循環(huán),通過flag來控制循環(huán)是否結束,主線程中休眠了1秒,將flag置為false,按說此時線程t1會檢測到flag為false,打印“線程t1停止了”,為何和我們期望的結果不一樣呢?運行上面的代碼我們可以判斷,t1中看到的flag一直為true,主線程將flag置為false之后,t1線程中并沒有看到,所以一直死循環(huán)。

那么t1中為什么看不到被主線程修改之后的flag?

要解釋這個,我們需要先了解一下java內存模型(JMM),Java線程之間的通信由Java內存模型(本文簡稱為JMM)控制,JMM決定一個線程對共享變量的寫入何時對另一個線程可見。從抽象的角度來看,JMM定義了線程和主內存之間的抽象關系:線程之間的共享變量存儲在主內存(main memory)中,每個線程都有一個私有的本地內存(local memory),本地內存中存儲了該線程以讀/寫共享變量的副本。本地內存是JMM的一個抽象概念,并不真實存在。它涵蓋了緩存,寫緩沖區(qū),寄存器以及其他的硬件和編譯器優(yōu)化。Java內存模型的抽象示意圖如下:

java高并發(fā)的volatile與Java內存模型詳解

從上圖中可以看出,線程A需要和線程B通信,必須要經歷下面2個步驟:

1.首先,線程A把本地內存A中更新過的共享變量刷新到主內存中去

2.然后,線程B到主內存中去讀取線程A之前已更新過的共享變量

下面通過示意圖來說明這兩個步驟:

java高并發(fā)的volatile與Java內存模型詳解

如上圖所示,本地內存A和B有主內存中共享變量x的副本。假設初始時,這三個內存中的x值都為0。線程A在執(zhí)行時,把更新后的x值(假設值為1)臨時存放在自己的本地內存A中。當線程A和線程B需要通信時,線程A首先會把自己本地內存中修改后的x值刷新到主內存中,此時主內存中的x值變?yōu)榱?。隨后,線程B到主內存中去讀取線程A更新后的x值,此時線程B的本地內存的x值也變?yōu)榱?。從整體來看,這兩個步驟實質上是線程A在向線程B發(fā)送消息,而且這個通信過程必須要經過主內存。JMM通過控制主內存與每個線程的本地內存之間的交互,來為java程序員提供內存可見性保證。

對JMM了解之后,我們再看看文章開頭的問題,線程t1中為何看不到被主線程修改為false的flag的值,有兩種可能:

1.主線程修改了flag之后,未將其刷新到主內存,所以t1看不到

2.主線程將flag刷新到了主內存,但是t1一直讀取的是自己工作內存中flag的值,沒有去主內存中獲取flag最新的值

對于上面2種情況,有沒有什么辦法可以解決?

是否有這樣的方法:線程中修改了工作內存中的副本之后,立即將其刷新到主內存;工作內存中每次讀取共享變量時,都去主內存中重新讀取,然后拷貝到工作內存。

java幫我們提供了這樣的方法,使用volatile修飾共享變量,就可以達到上面的效果,被volatile修改的變量有以下特點:

1.線程中讀取的時候,每次讀取都會去主內存中讀取共享變量最新的值,然后將其復制到工作內存

2.線程中修改了工作內存中變量的副本,修改之后會立即刷新到主內存

我們修改一下開頭的示例代碼:

?
1
public volatile static boolean flag = true;

使用volatile修飾flag變量,然后運行一下程序,輸出:

?
1
2
線程t1 in
線程t1停止了

這下程序可以正常停止了。volatile解決了共享變量在多線程中可見性的問題,可見性是指一個線程對共享變量的修改,對于另一個線程來說是否是可以看到的。\

總結

本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關注服務器之家的更多內容!

原文鏈接:https://itsoku.blog.csdn.net/article/details/100036220

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 日本热妇 | 白丝捆绑vk| ady成人映画网站官网 | 日本亚洲欧洲高清有码在线播放 | 动漫人物差差差动漫人物免费观看 | www.九九热 | 全黄一级裸片视频免费 | 大好硬好深好爽想要视频 | 欧美性野久久久久久久久 | 亚洲乱码尤物193yw在线播放 | 精品综合久久久久久88小说 | 16男男gaygays | 国产成人理在线观看视频 | 国产91在线九色 | 国产高清免费午夜在线视频 | 久久毛片基地 | 国产偷窥女洗浴在线观看亚洲 | 精品久久免费观看 | 亚欧有色在线观看免费版高清 | 国内偷拍第一页 | 2018生活片性色生活片 | 99精品国产自产在线观看 | 午夜DV内射一区区 | 日本肉体xxxx69xxxx | 久久国产精品高清一区二区三区 | 亚洲AV无码国产精品午夜久久 | 精品国产综合 | 日本又大又硬又粗的视频 | 亚洲品质自拍视频 | 无人视频在线观看完整版高清 | 娇妻被健身教练挺进小说阅读 | ass天天裸妇pics | 国产第一页无线好源 | 色婷婷婷丁香亚洲综合不卡 | 日本一区二区视频在线观看 | 99久久精品免费看国产一区 | 免看一级a一片成人123 | 国产精品成人麻豆专区 | 国产高清在线不卡 | 亚洲狠狠婷婷综合久久久久网站 | 国产日韩欧美不卡www |