なぜi++
Javaではアトミックではないのですか?
Javaを少し深くするために、スレッド内のループが実行される頻度を数えようとしました。
だから私は
private static int total = 0;
メインクラスで。
2つのスレッドがあります。
- スレッド1:プリント
System.out.println("Hello from Thread 1!");
- スレッド2:プリント
System.out.println("Hello from Thread 2!");
そして、スレッド1とスレッド2によって印刷された行を数えますが、スレッド1の行+スレッド2の行は、印刷された行の総数と一致しません。
これが私のコードです:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Test {
private static int total = 0;
private static int countT1 = 0;
private static int countT2 = 0;
private boolean run = true;
public Test() {
ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
newCachedThreadPool.execute(t1);
newCachedThreadPool.execute(t2);
try {
Thread.sleep(1000);
}
catch (InterruptedException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
run = false;
try {
Thread.sleep(1000);
}
catch (InterruptedException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println((countT1 + countT2 + " == " + total));
}
private Runnable t1 = new Runnable() {
@Override
public void run() {
while (run) {
total++;
countT1++;
System.out.println("Hello #" + countT1 + " from Thread 2! Total hello: " + total);
}
}
};
private Runnable t2 = new Runnable() {
@Override
public void run() {
while (run) {
total++;
countT2++;
System.out.println("Hello #" + countT2 + " from Thread 2! Total hello: " + total);
}
}
};
public static void main(String[] args) {
new Test();
}
}
iinc
整数をインクリメントする操作がありますが、これは、同時実行性が問題にならないローカル変数に対してのみ機能します。フィールドの場合、コンパイラーは読み取り-変更-書き込みコマンドを個別に生成します。
iinc
フィールドに対する命令があったとしても、単一の命令を持つことはアトミック性を保証しません。たとえば、非volatile
long
およびdouble
フィールドアクセスは、単一のバイトコード命令によって実行されるという事実に関係なく、アトミックであることが保証されません。
AtomicInteger
か?