簡體   English   中英

java 同步監視器進入對非同步訪問或非易失性變量的影響

[英]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易失的 booleanposition非易失的 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 的讀/寫操作,而是使用緩存值),如果我進入發生這種情況 1synchronized塊(因為可能,更新的 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM