简体   繁体   English

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

[英]happens-before relationship does not work as expected using "volatile"

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");

}

output: pool-1-thread-1: get start输出:pool-1-thread-1:开始
set start设置开始
set end设置结束
set start设置开始
set end设置结束
pool-1-thread-1: z is 0 pool-1-thread-1:z 为 0
pool-1-thread-1: x is 2 pool-1-thread-1: x 是 2
pool-1-thread-1: y is 2 pool-1-thread-1: y 是 2
pool-1-thread-1: get end pool-1-thread-1:结束

expected output: pool-1-thread-1: get start set start预期输出:pool-1-thread-1:get start set start
set end设置结束
set start设置开始
set end设置结束
pool-1-thread-1: z is 2 pool-1-thread-1:z 是 2
pool-1-thread-1: x is 2 pool-1-thread-1: x 是 2
pool-1-thread-1: y is 2 pool-1-thread-1: y 是 2
pool-1-thread-1: get end pool-1-thread-1:结束

why the output does not display the updated value of z with volatile keywords.为什么输出不显示带有 volatile 关键字的 z 的更新值。

This is because being volatile would simply force a read on the main memory for any atomic action done to/with it, but z++ is equivalent to z = z + 1 which means there are 2 actions in there: a read operation and a write operation.这是因为volatile只会强制读取主存储器上对其执行的任何原子操作,但z++等效于z = z + 1 ,这意味着其中有 2 个操作:读取操作和写入操作. Multiple threads can still read/write the value in between these 2 operations.多个线程仍然可以读/写这两个操作之间的值。

I guess you are looking for something like this: Use the synchronized keyword in your method.我猜您正在寻找这样的东西:在您的方法中使用synchronized关键字。 This ensures that the commands in this method are all executed as if it was only one statement.这确保了此方法中的命令都被执行,就好像它只是一个语句一样。 So nothing happens inbetween these statements.所以在这些语句之间什么也没有发生。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM