簡體   English   中英

為什么Java中的變量不是默認的volatile?

[英]Why aren't variables in Java volatile by default?

可能類似的問題:

你在Java中使用volatile關鍵字嗎?


今天我正在調試我的游戲; 它有一個非常困難的線程問題,每隔幾分鍾就出現一次,但很難重現。 所以首先我將synchronized關鍵字添加到我的每個方法中。 那沒用。 然后我將volatile關鍵字添加到每個字段。 問題似乎只是解決了問題。

經過一些實驗,我發現負責的字段是一個GameState對象,它跟蹤我的游戲當前狀態,可以是正在播放也可以是忙碌。 忙時,游戲會忽略用戶輸入。 我所擁有的是一個不斷更改state變量的線程,而Event線程則讀取state變量。 但是,在一個線程更改變量后,另一個線程需要幾秒鍾來識別更改,這最終會導致問題。

它是通過使狀態變量volatile修復的。

為什么默認情況下Java中的變量不是volatile ,以及不使用volatile關鍵字的原因是什么?

總而言之,易變量 - 無論是Java還是C# - 都不會在線程中本地緩存。 除非您正在處理在不同內核上執行線程的多處理器/多核CPU,否則這並沒有多大意義,因為它們正在查看相同的緩存。 當您將變量聲明為volatile時,所有讀取和寫入都直接來自並直接進入實際的主存儲器位置; 沒有涉及緩存。 當涉及到優化時,這會產生影響,並且不必要地(當大多數變量不需要變化時)這樣做會對相對較小的增益造成性能損失(盡管可能或可能不是很微不足道)。

當您嘗試編寫低級線程安全的無鎖代碼時,實際上只需要Volatiles。 您的大多數代碼可能不應該線程安全的或無鎖的。 根據我的經驗,你發現它確實做鎖定的簡單版本招致顯著的性能損失,由於鎖定后無鎖編程是唯一值得嘗試。

更令人愉快的選擇是在java.util.concurrent使用其他構建塊,其中一些是無鎖的,但不要像在低級別嘗試自己完成所有這一樣。

波動性有其自身的性能成本,並且大多數代碼都沒有理由承擔這些成本。

就個人而言,我認為字段應該是默認的最終字段,並且只有一個額外的關鍵字才可變,但是這條船在很久以前就已經航行了。 ;)

雖然其他人指出為什么默認為volatile是一個壞主意是正確的,但還有另外一點要做:代碼中很可能存在錯誤。 變量很少需要使用volatile:總是有一種方法可以正確地同步對變量的訪問(通過synchronized關鍵字,或者使用來自java.util.concurrency的AtomicXxx對象):異常包括操作這些的JNI代碼(不受同步約束)指令)。

因此,您可能想要找出解決問題的原因,而不是添加volatile。 它不是解決它的唯一方法,可能有更好的方法。

因為編譯器無法優化volatile變量。

volatile告訴編譯器變量可以隨時更改。 因此,它不能假設變量不會相應地改變和優化。

聲明變量volatile通常會對性能產生巨大影響。 在傳統的單線程系統中,相對容易知道需要變化的東西; 是那些訪問硬件的東西。

在多線程上它可能會稍微復雜一些,但我通常會鼓勵使用通知和事件隊列來處理魔術變量中的數據庫之間的數據傳遞。 在Java中它可能並不重要; 在C / C ++中,當這些變量無法由底層硬件原子設置時,您會遇到麻煩。

暫無
暫無

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

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