より転載 非常にトリッキーなJavaのインタビューの質問:私はそれがスレッドセーフである++します
私は、スレッドセーフ++しますか?
私はシニアのJava面接の多くは、この問題が発生していることを信じて、これの多くは強制的に非常に明確なフェイスマスクは確かではありません。ハートは確かにまだ私はまだスレッドの安全性の問題がある++、疑問?唯一の彼らのレベルを制限して、彼らは十分に知っていると言うことができます。
私はスレッドセーフではありません最後に++最初に確認するには、以下の例を考えてみましょう。
1000件のスレッド、共有変数count ++ 1000倍の動作の各。
-
static
int count =
0;
-
static CountDownLatch cdl =
new CountDownLatch(
1000);
-
-
/**
-
* 微信公众号:Java面经
-
*/
-
-
public static void main(String[] args) throws Exception {
-
-
CountRunnable countRunnable =
new CountRunnable();
-
for (
int i =
0; i <
1000; i++) {
-
new Thread(countRunnable).start();
-
}
-
-
cdl.await();
-
System.out.println(count);
-
}
-
-
-
static
class CountRunnable implements Runnable {
-
-
private void count() {
-
for (
int i =
0; i <
1000; i++) {
-
count++;
-
}
-
}
-
-
@Override
-
public void run() {
-
count();
-
cdl.countDown();
-
}
-
-
}
我々は結果が予想上記の例では、少なくとも今、あなたは私はそれがスレッドセーフではありません運転++を知って、あなたは常に1000000を見つけるだろう、1,000,000であってもよいが、N回実行する必要があります。
それを読んで、共有変数への書き込み原則としてJMMモデルを初めて目。
各スレッドは、独自のワーキングメモリ、共有変数の必要性は、このような操作が完了したときに、それらのワーキングメモリをロードし、メインメモリに共有変数を保存するために、メインメモリから変数を操作し、各スレッドなければならない最初のシェアを持っています。
問題は、スレッドがメインメモリにブラシ操作を終了していない場合、別のスレッドによって共有変数の値は、データは、データがダーティである今回読み取られ、メインメモリからそれを読み出すために、その中にありますこれは、値の計算の他のスレッドの終了をカバーします。。。
これは、メモリの古典的な問題が表示されていないで、それがこの問題を解決することができるかどうか、カウントプラス揮発性メモリを見てみましょうか? 答えは:なし。揮発性が唯一の可視性を保証することができますので、我々は原子性を保証することはできません。複数のスレッドが同時に他のスレッドは、視認性を確保変更しても、共有変数の値を読み取り、次いで、互いのカバレッジの値を同じ値を読み出すためのスレッド間で保証はありません。
「をご参照くださいマルチスレッドに関するいくつかの重要な概念、マルチスレッドのアトミック性、視認性、秩序を説明し、」この記事を。
ソリューション
ことを言って、私はそこにこのスレッド不安他のソリューション++の?もちろん、次の解決策を参照してください。
1つのみのスレッドがI ++の操作を行っている間、私は、プラス同期ロック++を操作する方法。
2は、アトミック操作の使用は、クラスをサポートし java.util.concurrent.atomic.AtomicInteger
、それは第一のタイプよりCASアルゴリズムより効率的に使用されます。