[英]Effect of java synchronized monitor enter on non synchronized access or not volatile variables
我有一個看起來像這樣的下載操作代碼
while(true){
if(target.flagStop){
break;
}else{
x=target.check();
}
len=in.read(buff,0,min(BUFFER_SIZE,x));
out.write(buff,0,len);
target.position+=len;
}
其中flagStop
是易失的 boolean和position
是非易失的 long值,在check()
方法中我有一個synchronized
塊
long check(){
//some code here
synchronized(aLock){
//some code here
return something;
}
}
我只在這個線程中更新(寫訪問) position
(只關心這個是否有最新的更新)但也發生了來自不同線程的一些讀取,我的情況只是出於監控目的,所以比我預期的要低幾個字節與將價值聲明為volatile
相比無關緊要,這在我的主要目的上會影響性能
我知道要完成一條 CPU 指令,計算進度結果將返回到 memory 后,數據到達 CPU 寄存器
- 如果該變量聲明為volatile
,則結果將立即寫入主 memory(不再緩存)
- 否則這將被存儲在線程緩存 memory 之后,以后這個值將被寫入主存儲器(從緩存寫入主 memory,時間無法確定(這可以立即或延遲無人知道)我的情況我的問題是關於這種情況,即價值不是volatile
的,而且只在一個線程中
根據 StackOverflow 中一位親愛的用戶的回答,當我們首先輸入synchronized
塊時
(案例 1):我們從主 memory 進行讀取操作(稱為讀取屏障)
並在synchronized
塊的末尾
(案例 2):我們對主 memory 進行了寫操作(稱為寫屏障)
我知道案例2
所有修改過的線程緩存變量都將寫入主 memory 但我可能認為錯誤的是情況 1:我們從主 memory 執行讀取操作,它使用存儲在主 ZCD69B4957F08CD861D 中的版本覆蓋線程緩存(main -> cache)
正如我之前提到的,我的position
值不是volatile
的(因此不能直接訪問對主 memory 的讀/寫操作,而是使用緩存值),如果我進入發生這種情況 1的synchronized
塊(因為可能,更新的 Z4757FE07FD4982A86EEA6 來自線程緩存還沒有機會將其值寫入主內存)並將 position 的主內存(可能較舊)版本覆蓋到線程緩存中(即通過覆蓋同步monitor enter
操作檢索到的舊值來銷毀較新的)
我真的這么想嗎?
我必須position
聲明為volatile
嗎?
並告訴我是否錯了, monitor enter
時線程緩存中發生的事情(或我之前提到的案例 1 )提前感謝您的指導。
您正在尋找的部分內容:
https://docs.oracle.com/javase/specs/jls/se14/html/jls-17.html#jls-17.4.1
可以在線程之間共享的 Memory 稱為共享 memory 或堆 memory。
所有實例字段、static 字段和數組元素都存儲在堆 memory 中。 在本章中,我們使用術語變量來指代字段和數組元素。
局部變量(第 14.4 節)、形式方法參數(第 8.4.1 節)和異常處理程序參數(第 14.20 節)永遠不會在線程之間共享,並且不受 memory model 的影響。
這里的“不受影響”意味着它們不需要同步。 只要只有一個線程看到一個變量,它總是沒問題的。
這也有助於:
https://docs.oracle.com/javase/specs/jls/se14/html/jls-17.html#jls-17.4.7
執行遵循線程內一致性。
對於每個線程 t,t 在 A [由該線程執行的操作] 中執行的操作與該線程以程序順序隔離生成的操作相同,每次寫入 w 寫入值 V(w),假設每個讀取 r 會看到值 V(W(r))。 每次讀取看到的值由 memory model 確定。 給定的程序順序必須反映根據 P 的線程內語義執行動作的程序順序。
操作意味着讀取和寫入。 所以你的變量position
因為同步而不允許用一些奇怪的值更新。 單個執行線程中的讀取和寫入按照程序語句指定的順序發生。 系統不會從緩存或主 memory 亂序中拉出奇怪的讀取或寫入。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.