使用“ volatile”之前发生的关系无法按预期工作

时间:2018-10-30 05:31:08

标签: java multithreading volatile happens-before

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:结束

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

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

我猜您正在寻找这样的东西:在您的方法中使用synchronized关键字。这样可以确保该方法中的所有命令都像一条语句一样全部执行。因此,这些语句之间什么也没发生。

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