亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Java中的StoreStore內存屏障是否禁止讀寫重新排序?

Java中的StoreStore內存屏障是否禁止讀寫重新排序?

largeQ 2023-09-13 17:58:54
現在我們有Load AStoreStoreStore B是否有可能實際的執行順序如下StoreStoreStore BLoad A如果可能的話,如何解釋似乎違反的情況The Java volatile Happens-Before Guarantee。據我所知,易失性語義是使用以下JMM內存屏障添加策略來實現的insert a StoreStore before volatile variable write operationinsert a StoreLoad after volatile variable write operationinsert a LoadLoad after volatile variable read operationinsert a LoadStore after volatile variable read operation現在如果我們有兩個 java 線程,如下所示線程1Load AStoreStoreStore volatile B線程2Load volatile BLoad C根據《The Java volatile Happens-Beforeguarantee》,Load A應該happens-before Load Cwhen Load volatile Bis after Store volatile B,但是如果Load A可以重新排序到“after Store volatile B”,如何保證Load A is before Load C?
查看完整描述

2 回答

?
慕勒3428872

TA貢獻1848條經驗 獲得超6個贊

從技術上講,Java 語言不存在內存障礙。相反,Java 內存模型是根據發生在關系之前指定的;詳細信息請參見以下內容:

  • Java 中內存屏障的行為

正如該文檔所說,它是為編寫實現 Java 內存模型的編譯器的人們提供的指南。它正在解釋JMM 的含義,顯然無意成為官方規范。JLS 是規范。

JSR-133 Cookbook 中有關內存屏障的部分根據它們限制特定加載和存儲序列的方式對它們進行分類。對于StoreStore障礙,它說:

該順序:Store1; StoreStore; Store2?確保 Store1 的數據在與 Store2 關聯的數據和所有后續存儲指令之前對其他處理器可見(即刷新到內存)。一般來說,StoreStore處理器上需要屏障,否則不能保證從寫入緩沖區和/或高速緩存到其他處理器或主存儲器的刷新的嚴格順序。

正如您所看到的,StoreStore障礙僅限制操作的行為store

在您的示例中,您有一個load后跟一個store。屏障的語義StoreStore沒有提及load操作。因此,您建議的重新排序是允許的。



查看完整回答
反對 回復 2023-09-13
?
有只小跳蛙

TA貢獻1824條經驗 獲得超8個贊

這只是回答您問題的更新部分。

首先,您提供的示例不是 Java 代碼。因此我們不能對其應用 JMM 推理。(只是為了讓我們清楚這一點。)

如果您想了解 Java 代碼的行為方式,請忘記內存屏障。Java 內存模型告訴您為了使內存讀取和寫入具有有保證的行為而需要執行的所有操作。以及推理(正確)行為所需了解的一切。所以:

  • 編寫您的 Java 代碼

  • 分析代碼以確保在線程需要讀取另一個線程寫入的值的所有情況下,鏈之前都有正確的發生。

  • 將(正確的)Java 代碼編譯為機器指令的問題留給編譯器。

查看示例中的偽指令序列,它們沒有多大意義。我不認為真正的 Java 編譯器在編譯真正的 Java 代碼時會(在內部)使用這樣的屏障。相反,我認為在每次易失性寫入之后和每次易失性讀取之前都會存在StoreLoad內存屏障。

讓我們考慮一些真實的 Java 代碼片段:

public int a;

public volatile int b;


// thread "one"

{

  a = 1;

  b = 2;

}


// thread "two"

  if (b == 2) {

      print(a);

  }

}

現在假設線程“二”中的代碼在線程“一”之后執行,將會有一個發生之前鏈,如下所示:

  • a = 1發生在之前b = 2

  • b = 2發生在之前b == 2

  • b == 2發生在之前print(a)

除非涉及其他代碼,否則發生之前鏈意味著線程“二”將打印“1”。

筆記:

  1. 編譯代碼時無需考慮編譯器使用的內存屏障。

  2. 這些障礙是特定于實現的并且是編譯器內部的。

  3. 如果您查看本機代碼,您將不會看到內存屏障本身。您將看到具有所需語義的本機指令,以確保(隱藏的)內存屏障存在。


查看完整回答
反對 回復 2023-09-13
  • 2 回答
  • 0 關注
  • 136 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號