【发布时间】:2014-09-29 20:12:04
【问题描述】:
为什么i++ 在 Java 中不是原子的?
为了更深入地了解 Java,我尝试计算线程中循环的执行频率。
所以我用了一个
private static int total = 0;
在主类中。
我有两个线程。
- 线程 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();
}
}
【问题讨论】:
-
你为什么不试试
AtomicInteger? -
JVM 有一个用于递增整数的
iinc操作,但这仅适用于不考虑并发性的局部变量。对于字段,编译器分别生成read-modify-write命令。 -
你为什么会期望它是原子的?
-
@Silly Freak:即使字段有
iinc指令,单条指令也不能保证原子性,例如非volatilelong和double字段访问不能保证是原子的,不管它是由单个字节码指令执行的。
标签: java multithreading concurrency