簡體   English   中英

在 Java 中編寫 long 和 double 不是原子的嗎?

[英]Writing long and double is not atomic in Java?

讀取和寫入單個變量是原子的(語言保證!),除非變量是 long 或 double 類型。

我正在閱讀一門課程的幻燈片,我發現它已經寫好了。 這門課是關於並發的。

誰能向我解釋為什么寫 long 或 double 不是原子操作? 着實讓我大吃一驚。

它不是原子的,因為它是機器代碼級別的多步驟操作。 也就是說,longs 和 doubles 比處理器的字長要長。

只是為了澄清 Java 的情況,除非聲明為volatile否則不會以原子方式讀取或寫入雙精度型和長型

JLS - 非原子處理雙和長

Java long 和 double 在 32 位機器中不是原子的,而是在帶有一些 64 位 JVM 的 64 位機器中是原子的。 為什么它依賴於機器位長度? 因為 32 位機器需要兩次寫入 long(因為 long 是 64 位)。 閱讀本文了解詳細信息。

很多程序員在實踐java並發中的“3.1.2.非原子64位操作”中的這句話想必都看過了。 我已經提到了最新的 JLS 17.7。 double 和 long 的非原子處理 如今,他們仍然沒有聲稱 64 位 JVM 是常態。 因此,64 位操作被分解為 32 位操作,這些操作破壞了原子性,並且在聲明 volatile 之前在多線程環境中使用是危險的。 Long 和 double 在 java 中是 64 位長。 所以寫和讀操作在java中不是原子的。

Java 編程語言內存模型,對非易失性 long 或 double 值的單次寫入被視為兩次單獨的寫入:一次寫入每個 32 位一半。 這可能導致線程從一次寫入中看到 64 位值的前 32 位,而從另一次寫入中看到后 32 位的情況。

閱讀 maaartinus 的回答@Java 中的哪些操作被認為是原子的?
閱讀 Jon Skeet 的回答@ 當原始數據類型在 Java 中不是線程安全的?

根據JLS,您可以通過將 double 和 long 聲明為 volatile 來使讀和寫操作成為原子操作。 但這並不能確保 ++ 是原子的。 這需要 concurrent.atomic 包。
閱讀 Louis Wasserman 的回答

還有這個博客和評論。

原子變量操作意味着任何線程都可以讀取/寫入它而不會產生任何垃圾

由於硬件限制,非long / double讀/寫對於 x32 和一些x64 是atomic的。 如果使用volatile ,它會使其/添加到atomic

[原子性]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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