为什么Java基本变量赋值不是原子的

时间:2017-12-15 05:46:04

标签: java

所有。我运行以下代码来测试Java基本变量赋值是否为原子。

public class Test  {
static int x = 1 << 16 - 1, y = -1 << 16, i = x;
static volatile boolean flag = false;
public static void main(String... args) {
    ExecutorService executors = Executors.newFixedThreadPool(3);
    executors.execute(() -> {
        while (true) {
            if (flag) {
                return;
            }
            i = x;
        }
    });
    executors.execute(() -> {
        while (true) {
            if (flag) {
                return;
            }
            i = y;
        }
    });
    executors.execute(() -> {
        while (true) {
            if (i != x && i != y && (flag = true)) {
                System.out.println(i + "," + x + "," + y);
                throw new RuntimeException("Not Equal!!");
            }
        }
    });
}

它会抛出一个新的异常(跟随文本),但是当条件(i!= x&amp;&amp; i!= y)为真时我无法捕捉到实际的i,因为其他线程会修改变量i at同时。

Exception in thread "pool-1-thread-3" java.lang.RuntimeException: Not Equal!!
at common.Test.lambda$main$2(Test.java:31)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)

32768,32768,-65536

有人可以提供一些有用的建议来帮助我找出实际的原因(如果(i!= x&amp;&amp; i!= y&amp;&amp;(flag = true))是真的吗?

1 个答案:

答案 0 :(得分:0)

你看到的问题不是因为int赋值不是原子的:它是!

由于您正在从多个线程修改i,因此应对所有读取和写入进行同步,否则线程可能会获得过时值,这就是您的情况,例如:

  1. 任务i = y
  2. 评估此条件:if (i != x && i != y && (flag = true))
  3. 评估
  4. i != x并返回true
  5. 任务i = x
  6. 评估
  7. i != y并返回true
  8. 我们在if
  9. 里面