問題:synchorized,sleep 也能達到volatile 線程可見性的目的?,大致的問題描述如下:
# package com.test;
import java.util.concurrent.TimeUnit;
# public class test1 {
private static boolean is = true;
public static void main(String[] args) {
# new Thread(new Runnable() {
@Override
public void run() {
# int i = 0;
while(test1.is){
# i ;
1 //synchronized (this) { } 會強制刷新主記憶體的變數值到線程堆疊?
# 2 //System.out.println("1"); println 是synchronized 的,會強制刷新主記憶體的變數值到線程堆疊?
3 //sleep 會從新load主記憶體的值?
// try {
// TimeUnit.MICROSECONDS.sleep(1);
# // }catch (InterruptedException e) {
// e.printStackTrace();
# // }
}
}
}).start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
# }
new Thread(new Runnable() {
@Override
public void run() {
# is = false; //設定is為false,使上面的執行緒結束while迴圈
}
}).start();
}
}
問: 為什麼整個程式不會終止?為什麼取消註解中的任何一個程式碼區塊(1,2,3),程式才會終止? synchronized 會強制刷新住記憶體的變數值到執行緒堆疊? sleep 會做什麼呢?
涉及知識解釋
volatile:此關鍵字保證了變量在線程的可見性,所有線程訪問由volatile修飾的變量,都必須從主存中讀取後操作,並在工作內存修改後立即寫回主存,保證了其他線程的可見性,同樣效果的關鍵字還有final。
synchronized:所有同步操作都必須保證 1、原子性 2、可見性,所以在同步區塊中發生的變化會立刻寫回主記憶體
sleep:此方法只會讓出CPU執行時間,並不會釋放鎖定。
問題分析
Q1:為什麼註解程式碼後程式不會終止?
A1:因為boolean is=true 的變數值被前面線程(簡稱線程A)加載到自己的工作內存,在後面的線程(簡稱線程B)改變boolean is=false 之後不一定會立刻寫入主存(不過這題中應該會馬上寫入主存,因為線程執行完is=false之後線程就要退出了),即使立馬寫入了主存後線程A也不一定馬上load到工作內存中,所以程序一直不會終止?這是我們大多數人想到的,但其實JVM針對現在的硬體水平已經做了很大程度的優化,基本上很大程度的保障了工作內存和主內存的及時同步,相當於默認使用了volatile。但只是最大程度!在CPU資源一直被佔用的時候,工作記憶體與主記憶體中間的同步,也就是變數的可見度就會比較不及時!後面會驗證結論。
Q2:為什麼取消註解中的任何一個程式碼區塊(1,2,3),程式才會終止?
A2:行號為1、2的程式碼有一個共同特點,就是都涉及到了synchronized 同步鎖,那麼是否像提問作者猜想的那樣synchronized會強制刷新主記憶體的變數值到線程棧? ,以及sleep方法也會刷新主存的變數值到執行緒棧呢? ,事實上我們前面說了synchronized只會保證在同步區塊中的變數的可見性,而is變數並不在該同步區塊中,所以顯然不是這個導致的。接下來我們在程式碼i ;後面加上以下程式碼:
# for(int k=0;k
new Object();
}
再Run,程式立刻終止!為什麼?在上面的A1 中我們已經說了即便有JVM的優化,但當CPU一直被佔用的時候,資料的可見性得不到很好的保證,就像上面的程式一直循環做i ;運算佔用CPU,而為什麼加上上面的程式碼後程式就會停止呢?因為對於大量new Object()操作來說,CPU已經不是主要佔時間的操作,真正的耗時應該在內存的分配上(因為CPU的處理速度明顯快過內存,不然也不會有CPU的寄存器了),所以CPU空閒後會遵循JVM優化基準,盡可能快的保證資料的可見性,從而從主存同步is變數到工作內存,最終導致程序結束,這也是為什麼sleep()方法雖然沒有涉及同步操作,但是依然可以使程式終止,因為sleep()方法會釋放CPU,但不會釋放鎖定!
以上是Java變數的可見性問題實例分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本文討論了使用Maven和Gradle進行Java項目管理,構建自動化和依賴性解決方案,以比較其方法和優化策略。

本文使用Maven和Gradle之類的工具討論了具有適當的版本控制和依賴關係管理的自定義Java庫(JAR文件)的創建和使用。

本文討論了使用咖啡因和Guava緩存在Java中實施多層緩存以提高應用程序性能。它涵蓋設置,集成和績效優勢,以及配置和驅逐政策管理最佳PRA

本文討論了使用JPA進行對象相關映射,並具有高級功能,例如緩存和懶惰加載。它涵蓋了設置,實體映射和優化性能的最佳實踐,同時突出潛在的陷阱。[159個字符]

Java的類上載涉及使用帶有引導,擴展程序和應用程序類負載器的分層系統加載,鏈接和初始化類。父代授權模型確保首先加載核心類別,從而影響自定義類LOA


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

記事本++7.3.1
好用且免費的程式碼編輯器

MinGW - Minimalist GNU for Windows
這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

EditPlus 中文破解版
體積小,語法高亮,不支援程式碼提示功能

SublimeText3 Linux新版
SublimeText3 Linux最新版