首页 > 解决方案 > 并发导致的不同输出

问题描述

public class InstructionReorder {

    public int v1=1;
    public int v2=1;

    void foo() {
        v1 = v2+1;
        v2 = 0;
        System.out.println(String.format("%d and %d",v1,v2));
    }

    public static void main(String[] args) throws Exception {
        final InstructionReorder ir = new InstructionReorder();
        for (int i=0;i<Runtime.getRuntime().availableProcessors()>>2;i++) {
            new Thread(ir::foo).start();
        }
        Thread.sleep(1000);
    }
}

代码有不同的输出,有时会得到 output1:

2 and 0
1 and 0
1 and 0
1 and 0
1 and 0
1 and 0
1 and 0
1 and 0

或者有时得到输出2:

1 and 0
1 and 0
1 and 0
1 and 0
1 and 0
1 and 0
1 and 0
1 and 0

output1 是预期的结果。如果我同步方法,我得到了 output1,但我不想使用锁。我尝试了 volatile,但没有效果。
没有锁怎么修?

标签: javaconcurrency

解决方案


您看到的行为与指令重新排序无关,而是与并发访问有关。如果您想用 Java 编写正确的多线程代码,请查看“Java Concurrency in Practice”。

简而言之,您只需要使用一个同步块进行 v1 和 v2 访问。


推荐阅读