マルチスレッドの概念を試すだけで、私は悲観的なロックを使用するAtomicIntegerの独自のバージョンを実装しています。プリミティブなインスタンス変数をvolatileにする必要がありますか?
public class ThreadSafeInt {
public int i; // Should this be volatile?
public ThreadSafeInt(int i) {
this.i = i;
}
public synchronized int get() {
return i;
}
public synchronized int getAndIncrement() {
return this.i++;
}
// other synchronized methods for incrementAndGet(), etc...
}
私は、ThreadSafeIntのインスタンスを取りテストを書いたスレッドの数百人にそれを与え、それらのスレッドのそれぞれが10万回getAndIncrementを呼び出します:それは次のようになります。私が見ているのは、整数の値が正確に(number of threads) * (number of increments per thread)
であり、プリミティブなインスタンス変数i
でvolatileを使用していないにもかかわらず、すべての増分が正しく行われることです。私は、私はi
が揮発しなかった場合、私は、例えば、スレッド1ずつ1から0からi
が、スレッド2はまだ0の値を見て、視認性の問題の多くを得るだろうし、また、唯一の1
にそれをインクリメントすることを期待しました正しい値よりも小さい最終値が生じます。
私は私のテストは、可視性の問題のための固有の可能性があっても正常に動作するように見えることができるように、視認性の問題は、ランダムに発生し、私の環境の特性に依存することを理解しています。だから私は揮発性のキーワードがまだ必要であると思う傾向がある。
しかし、これは正しいでしょうか?または、私のコードのいくつかのプロパティがありますか(おそらく、それがちょうど原始的な変数であるという事実)、私は実際に揮発性キーワードの必要性を取り除くために信頼できるでしょうか?私は原始的なインスタンス変数に揮発使用していないにもかかわらず、
あなたは、コードパスが一度に1つのスレッドでしか実行できないことを保証するだけでなく、同期ブロック内で触れられた変数がvolatileであるかのように扱われることを保証しますか?私はあなたが同期を使用しても、2つのスレッドが変数内の異なる値を観測する可能性があると考えました。つまり、あなたが言っているのは、そうではないということです。 – russell
また、私は 'LongAdder'に渡してもよいでしょう。 –
@russellこれが本当に意味するのは、通常、アトミックな操作ではない 'i ++'は、 'synchronized'のためにアトミックになります。 –