在Java Servlet Programming這本書中,第54頁的示例servlet在後臺線程中搜索素數。每次客戶端訪問servlet時,都會返回最近找到的素數。java servlet中多個線程訪問的變量是否需要聲明爲volatile?
它用於存儲最近發現黃金被宣佈爲變量:
long lastprime = 0;
因爲這個變量開始從多個線程(後臺線程正在做的計算和任何客戶端線程訪問的正在訪問它),是否需要聲明爲volatile或以某種方式同步其訪問?
在Java Servlet Programming這本書中,第54頁的示例servlet在後臺線程中搜索素數。每次客戶端訪問servlet時,都會返回最近找到的素數。java servlet中多個線程訪問的變量是否需要聲明爲volatile?
它用於存儲最近發現黃金被宣佈爲變量:
long lastprime = 0;
因爲這個變量開始從多個線程(後臺線程正在做的計算和任何客戶端線程訪問的正在訪問它),是否需要聲明爲volatile或以某種方式同步其訪問?
是的,假設您真的想在任何線程上看到最近計算的素數,它應該是易失性的或者通過blocks/methods以線程安全的方式訪問。此外,正如註釋中指出的那樣,非易失性長變量可能不會自動更新 - 因此您可以看到舊值的前32位和新值的下32位(反之亦然)。
我忘記了事物的原子性側早些時候,因爲它幾乎總是通過當你確保你得到最新發布的價值,並確保您完全發佈新值自動解決。在實踐中,這幾乎總是你想要的,所以如果你的代碼能夠正常工作,原子性就成爲一個非問題。
這不是SingleThreadModel
servlet是它嗎?這顯然會有所作爲。
另一種選擇是使用AtomicLong
。
是的。一個servlet的變量不是線程安全的。
線程之間存在乾淨的讀/寫拆分;一個線程「發佈」最後一個素數供其他人閱讀,那麼你就可以使其變得不穩定。
如果訪問模式涉及一些讀取 - 修改 - 寫入序列等,那麼您必須將訪問權限同步到該字段。
假設Java 5或更高版本,則聲明它爲volatile將提供明確定義的語義,如描述here。關於從代碼維護者的頭腦中消除疑問的原則,我會使用volatile,並說「是的,我知道多個線程使用這個變量」。
問題是沒有聲明它是揮發性的影響。假設你有a素數,如果它是最新的可用性,它是否重要?易失性確保從內存中獲取值,而不是任何「CPU」緩存,所以您應該獲得更新的值。
如何看到部分分配的可能性?您是否真的不走運,看到一個長期的LSB是舊價值的一部分,MSB是不同價值的一部分?那麼,長期和雙打的任務不是原子的,理論上是這樣!
Ergo,易失性或同步不只是一個很好的... ...你需要它在Java中的volatile變量的
語義是沒有強大到足以使增值業務(lastprime ++)原子,除非你能保證變量從單個線程只寫了 - 不是在servlet的情況下
另一方面,只要沒有執行復合操作,使用AtomicXXX變量是線程安全的。更新多個原子變量時會出現漏洞窗口,即使每次調用都是原子的。
我會爲AtomicLong投票 – 2009-07-29 14:56:51