【问题标题】:happens-before relationship does not work as expected using "volatile"使用“volatile”之前发生的关系无法按预期工作
【发布时间】:2018-10-30 05:31:07
【问题描述】:
int x,y;
volatile int z;

public static void main(String[] args) {
    ThreadPoolExecutor pool = (ThreadPoolExecutor)Executors.newFixedThreadPool(5);
    MainTest mission = new MainTest();
    pool.execute(new MissionRead(mission));

    pool.execute(new MissionWrite(mission));
            pool.execute(new MissionWrite(mission));

    pool.shutdown();
}

public void set() {
    System.out.println("set start");
    x++;

    y++;z++;

    System.out.println("set end");

}

public void get() {
    System.out.println(Thread.currentThread().getName() +": get start");
    System.out.println(Thread.currentThread().getName() +": z is " + z);
    System.out.println(Thread.currentThread().getName() + ": x is " +  x);
    System.out.println(Thread.currentThread().getName() +": y is " + y);
    System.out.println(Thread.currentThread().getName() +": get end");

}

输出:pool-1-thread-1:开始
设置开始
设置结束
设置开始
设置结束
pool-1-thread-1:z 为 0
pool-1-thread-1: x 是 2
pool-1-thread-1: y 是 2
pool-1-thread-1: 结束

预期输出:pool-1-thread-1:开始 设置开始
设置结束
设置开始
设置结束
pool-1-thread-1:z 为 2
pool-1-thread-1: x 是 2
pool-1-thread-1: y 是 2
pool-1-thread-1: 结束

为什么输出不显示带有 volatile 关键字的 z 的更新值。

【问题讨论】:

标签: java multithreading volatile happens-before


【解决方案1】:

这是因为volatile 只会强制读取主内存以执行对其执行的任何原子操作,但z++ 等效于z = z + 1,这意味着其中有两个操作:读取操作和写操作。多个线程仍然可以在这两个操作之间读取/写入值。

【讨论】:

    【解决方案2】:

    我猜你正在寻找这样的东西:在你的方法中使用 synchronized 关键字。这确保了该方法中的命令都被执行,就好像它只是一个语句一样。所以这些语句之间没有任何反应。

    public synchronized void set() {
        System.out.println("set start");
        x++;
        y++;
        z++;
        System.out.println("set end");
    }
    

    【讨论】:

    • 我认为这不是由 z++ 之间发生读取引起的,因为可以看到 'set end' 在打印出 'z' 的值之前已经打印了两次。
    猜你喜欢
    • 2017-07-13
    • 1970-01-01
    • 2015-10-26
    • 2014-10-22
    • 2012-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-22
    相关资源
    最近更新 更多