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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

java 中violate_Java中的volatile关键字及Cache更新

發布時間:2023/12/20 java 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 中violate_Java中的volatile关键字及Cache更新 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Volatile [?vɑ?l?tl],中文解釋:反復無常的,易變的,不穩定的。

volatile的本意是告訴編譯器,此變量的值是易變的,每次讀寫該變量的值時務必從該變量的內存地址中讀取或寫入,不能為了效率使用對一個“臨時”變量的讀寫來代替對該變量的直接讀寫。編譯器看到了volatile關鍵字,就一定會生成內存訪問指令,每次讀寫該變量就一定會執行內存訪問指令直接讀寫該變量。若是沒有volatile關鍵字,編譯器為了效率,只會在循環開始前使用讀內存指令將該變量讀到寄存器中,之后在循環內都是用寄存器訪問指令來操作這個“臨時”變量,在循環結束后再使用內存寫指令將這個寄存器中的“臨時”變量寫回內存。在這個過程中,如果內存中的這個變量被別的因素(其他線程、中斷函數、信號處理函數、DMA控制器、其他硬件設備)所改變了,就產生數據不一致的問題。

volatile關鍵字在用C語言編寫嵌入式軟件里面用得很多,不使用volatile關鍵字的代碼比使用volatile關鍵字的代碼效率要高一些,但就無法保證數據的一致性。

在Java中,volatile 會確保我們對于這個變量的讀取和寫入,都一定會同步到主內存里,而不是從 Cache 里面讀取。

Case 1

public class VolatileTest {

private static volatile int COUNTER = 0;

public static void main(String[] args) {

new ChangeListener().start();

new ChangeMaker().start();

}

static class ChangeListener extends Thread {

@Override

public void run() {

int threadValue = COUNTER;

while ( threadValue < 5){

if( threadValue!= COUNTER){

System.out.println("Got Change for COUNTER : " + COUNTER + "");

threadValue= COUNTER;

}

}

}

}

static class ChangeMaker extends Thread{

@Override

public void run() {

int threadValue = COUNTER;

while (COUNTER <5){

System.out.println("Incrementing COUNTER to : " + (threadValue+1) + "");

COUNTER = ++threadValue;

try {

Thread.sleep(500);

} catch (InterruptedException e) { e.printStackTrace(); }

}

}

}

}

在這個程序里,我們先定義了一個 volatile 的 int 類型的變量,COUNTER。然后,我們分別啟動了兩個單獨的線程,一個線程我們叫 ChangeListener。

ChangeListener 這個線程運行的任務很簡單。它先取到 COUNTER 當前的值,然后一直監聽著這個 COUNTER 的值。一旦 COUNTER 的值發生了變化,就把新的值通過 println 打印出來。直到 COUNTER 的值達到 5 為止。這個監聽的過程,通過一個永不停歇的 while 循環的忙等待來實現。

另外一個 ChangeMaker 線程運行的任務同樣很簡單。它同樣是取到 COUNTER 的值,在 COUNTER 小于 5 的時候,每隔 500 毫秒,就讓 COUNTER 自增 1。在自增之前,通過 println 方法把自增后的值打印出來。

最后,在 main 函數里,我們分別啟動這兩個線程,來看一看這個程序的執行情況。

Incrementing COUNTER to : 1

Got Change for COUNTER : 1

Incrementing COUNTER to : 2

Got Change for COUNTER : 2

Incrementing COUNTER to : 3

Got Change for COUNTER : 3

Incrementing COUNTER to : 4

Got Change for COUNTER : 4

Incrementing COUNTER to : 5

Got Change for COUNTER : 5

程序的輸出結果并不讓人意外。ChangeMaker 函數會一次一次將 COUNTER 從 0 增加到 5。因為這個自增是每 500 毫秒一次,而 ChangeListener 去監聽 COUNTER 是忙等待的,所以每一次自增都會被 ChangeListener 監聽到,然后對應的結果就會被打印出來。

終極原因是:volatile保證所有數據的讀和寫都來自主內存。ChangeMaker 和 ChangeListener 之間,獲取到的 COUNTER 值就是一樣的。

Case 2

如果我們把上面的程序小小地修改一行代碼,把我們定義 COUNTER 這個變量的時候,設置的 volatile 關鍵字給去掉,重新運行后發現:

Incrementing COUNTER to : 1

Incrementing COUNTER to : 2

Incrementing COUNTER to : 3

Incrementing COUNTER to : 4

Incrementing COUNTER to : 5

這個時候,ChangeListener 又是一個忙等待的循環,它嘗試不停地獲取 COUNTER 的值,這樣就會從當前線程的“Cache”里面獲取。于是,這個線程就沒有時間從主內存里面同步更新后的 COUNTER 值。這樣,它就一直卡死在 COUNTER=0 的死循環上了。

Case 3

再對程序做一個小的修改。我們不再讓 ChangeListener 進行完全的忙等待,而是在 while 循環里面,Sleep 5 毫秒,看看會發生什么情況。

static class ChangeListener extends Thread {

@Override

public void run() {

int threadValue = COUNTER;

while ( threadValue < 5){

if( threadValue!= COUNTER){

System.out.println("Sleep 5ms, Got Change for COUNTER : " + COUNTER + "");

threadValue= COUNTER;

}

try {

Thread.sleep(5);

} catch (InterruptedException e) { e.printStackTrace(); }

}

}

}

運行結果:

Incrementing COUNTER to : 1

Sleep 5ms, Got Change for COUNTER : 1

Incrementing COUNTER to : 2

Sleep 5ms, Got Change for COUNTER : 2

Incrementing COUNTER to : 3

Sleep 5ms, Got Change for COUNTER : 3

Incrementing COUNTER to : 4

Sleep 5ms, Got Change for COUNTER : 4

Incrementing COUNTER to : 5

Sleep 5ms, Got Change for COUNTER : 5

解釋: 雖然沒有使用 volatile 關鍵字強制保證數據的一致性,但是短短 5ms 的 Thead.Sleep 的線程會讓出CPU,線程被喚醒后才會去重新加載變量。它也就有機會把最新的數據從主內存同步到自己的高速緩存里面了。于是,ChangeListener 在下一次查看 COUNTER 值的時候,就能看到 ChangeMaker 造成的變化了。

雖然 JMM 只是 Java 虛擬機這個進程級虛擬機里的一個隔離了硬件實現的虛擬機內的抽象模型,但是這個內存模型,和計算機組成里的 CPU、高速緩存和主內存組合在一起的硬件體系非常相似。以上就是一個很好的“緩存同步”問題的示例。也就是說,如果我們的數據,在不同的線程或者 CPU 核里面去更新,因為不同的線程或 CPU 核有著各自的緩存,很有可能在 A 線程的更新,因為數據暫時不一致,在 B 線程里面是不可見的。

參考:

如果不介意,歡迎使用我的分享鏈接,讓我賺幾個G幣:

總結

以上是生活随笔為你收集整理的java 中violate_Java中的volatile关键字及Cache更新的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 国产探花一区二区 | 欧美人妻精品一区二区 | 日韩女优中文字幕 | 91桃色在线观看 | 爱操影院 | 99久久国产宗和精品1上映 | www.蜜桃av.com | 久久久1| 久草av在线播放 | 色屋视频 | 男人深夜影院 | 视色影视| 奇米影视久久 | 午夜成人免费电影 | 国产又粗又猛 | 欧美日韩视频网站 | 国产激情对白 | 日韩毛片av | 91快色 | 色偷偷人人澡人人爽人人模 | 亚洲免费精品视频在线观看 | 亚洲一区二区三区网站 | 女人被狂躁60分钟视频 | 性视频播放免费视频 | 欧美日韩一区二区久久 | 天堂av亚洲av国产av电影 | 日本黄色片在线播放 | 国产视频a | 欧美黄色网 | www色婷婷| 91高清在线免费观看 | 奇米影视亚洲春色 | 久久在线免费观看视频 | 一卡二卡三卡四卡在线 | aise爱色av| 91丝袜视频 | 免费av大全 | 欧美日韩免费一区 | 国产成人高清视频 | 日韩毛片免费观看 | 美景之屋电影免费高清完整韩剧 | 先锋资源av网| 国产成人精品免费看视频 | 婷婷射 | 在线观看国产三级 | 国产毛片a | www.亚洲精品 | 香蕉一区二区三区四区 | 在线视频污 | 青青国产在线视频 | 欧美日韩午夜激情 | 老熟妇午夜毛片一区二区三区 | 美女av片| 娇妻被肉到高潮流白浆 | 国产精品精品 | 精品一区二区三区免费视频 | 精品自拍第一页 | 四虎在线影院 | 天天躁日日躁狠狠躁喷水 | 久久小草 | 久久精品69 | 老司机深夜福利影院 | 久久久久国产精品区片区无码 | 捅肌肌| 天天插天天射天天干 | 久久午夜精品人妻一区二区三区 | 男人网站在线观看 | 日韩欧美二区三区 | av黄在线观看 | 日韩国产成人无码av毛片 | 9999av| 黄视频免费在线观看 | 国产在线观看免费 | 久久久久婷| 在线观看视频毛片 | 九九九免费 | 午夜影院美女 | 中文国产视频 | 成人综合色站 | 欧美视频一区二区三区四区在线观看 | xxxxhdvideos | 欧美国产一级片 | 日韩一级在线观看视频 | 欧美精品观看 | 免费在线观看av网站 | av999| 五月婷婷综合激情 | 少妇一级淫片免费看 | 亚洲女人天堂网 | 午夜激情网站 | 黄色在线观看网站 | 日韩av自拍偷拍 | 99riav3国产精品视频 | 久久视频中文字幕 | 日日夜操 | 国产亚洲AV无码成人网站在线 | 97人人模人人爽人人少妇 | 欧美精品大片 | 久热精品在线视频 |