我讀過,當線程訪問變量以確保線程看到正確的值時,應該使用volatile,但是這也適用於在方法內使用變量的情況嗎?
這在多個方面都不準確*。
首先:volatile
只能在字段上使用。它不能用於其他類型的變量;即局部變量或參數。 (原因:這是毫無意義的,因爲其他類型的變量只對一個線程可見)。
其次:volatile
語義適用於是否使用方法調用。 (或塊)。使用方法(或塊)。但是正確使用通常以全部爲條件使用同步構造來執行訪問和更新。任何非同步訪問或更新可能呈現程序(作爲一個整體)不正確。
最後:volatile
方式訪問到外地會看到該字段的值的最新值。這不足以保證的正確性。例如:
public Counter {
private volatile int count;
public void increment() {
// This is NOT correct.
count++;
}
}
的原因,上面的例子是不正確的是count++
不是原子。它實際上意味着(字面上)count = count + 1
,而另一個線程可能會在訪問它的當前線程和寫回更新值之間更改count
。這會導致偶爾丟失的增量。
這是很容易看到,該聲明max
爲volatile
,並擺脫了關鍵字的代碼的版本將完全相同的原因是不正確的。您目前的版本在這方面更爲正確。但是,它仍然不完全正確,因爲沒有任何東西阻止其他類(在同一個包中)訪問或更新max
。如果這是在一個不同的線程中完成的,那麼除了漏洞抽象之外,你還會遇到一個潛在的併發問題。
因此,要回答你的問題:
它是安全的假設,如果多線程調用DoSomething的,那麼最多將被設置爲相同的狀態時,前一個線程調用的方法?
不完全是因爲漏洞的抽象。 (聲明max
是私有修復了這個。)
因爲DoSomething的()是同步的,我知道,只有一個線程可以修改最大,但是當一個線程調用它會發生什麼?
塊可確保在同一對象上同步的下一個線程將看到這些更新。 (如何實現平臺特定...)
最大可以是不同的值,因爲它不使用易失性?
不......模泄漏抽象問題。
或者它是安全的,因爲「限制器」實例修改它本身?
這其實是無關這個代碼的線程安全/正確性。重要的是同步,而不是自我修改。
*至少,你的你已經被你已經閱讀明白了總結是不正確的。對於我們所知的一切,您閱讀的原文可能是正確的。
UPDATE
我讀談論字段中的一部分(如由線程訪問的變量)。對困惑感到抱歉。我想知道的是,它是否也適用於由線程調用的對象中的方法使用的所有變量。
這適用於線程讀取和/或寫入的對象的所有字段都由同步區域覆蓋。實際上,它適用於其他對象的字段,以及在該區域中讀取/寫入的數組的元素。 (對於不是字段的變量是「無意的」,因爲沒有其他線程可以看到它們。)
但是,需要注意的是,它只適用於同步點。如果第二個線程沒有正確同步,所有投注都關閉。
我讀的部分是關於字段(如在線程可訪問的變量中)。對困惑感到抱歉。我想知道的是,它是否也適用於由線程調用的對象中的方法使用的所有變量。 – Mstr 2012-03-11 16:57:38