Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么使用两个可变变量进行重新排序?_Java_Concurrency_Volatile_Java Memory Model - Fatal编程技术网

Java 为什么使用两个可变变量进行重新排序?

Java 为什么使用两个可变变量进行重新排序?,java,concurrency,volatile,java-memory-model,Java,Concurrency,Volatile,Java Memory Model,我试图研究java环境中的重新排序行为(使用JDK 9-ea+170),发现了一件我自己无法解释的事情,所以我很高兴听到一些关于它的注释。下面是一个例子: public class Client { int x; int y; public void test() { x++; y++; } public static void main(String[] args) { Client c = new Cli

我试图研究java环境中的重新排序行为(使用JDK 9-ea+170),发现了一件我自己无法解释的事情,所以我很高兴听到一些关于它的注释。下面是一个例子:

public class Client {
    int x;
    int y;
    public void test() {
        x++;
        y++;
    }
    public static void main(String[] args) {
        Client c = new Client();
        while(c.y <= c.x) new Thread(() -> c.test()).start();
        System.out.println(c.x + " " + c.y);
    }
}
这个程序永远不会结束,因为volatile保证volatile之前的所有指令都将刷新到内存中,所以
x++始终在
y++之前执行并且y>x是不可能的。这也是我的理解。但在此之后,我将volatile添加到
intx太多,现在我可以再次看到重新排序,所以程序大部分时间结束:

public class Client {
    volatile int x;
    volatile int y;
    public void test() {
        x++;
        y++;
    }
    public static void main(String[] args) {
        Client c = new Client();
        while(c.y <= c.x) new Thread(() -> c.test()).start();
        System.out.println(c.x + " " + c.y);
    }
}
公共类客户端{
挥发性int x;
挥发性内质网;
公开无效测试(){
x++;
y++;
}
公共静态void main(字符串[]args){
客户机c=新客户机();
而(c.y c.test()).start();
System.out.println(c.x+“”+c.y);
}
}

为什么这里也会发生重新排序

这不是重新排序的证据。事实上,所发生的事情是
++
上的
易失性
不是原子的结果。例如,在更新一个变量时,考虑以下两个线程(<代码> A<代码/代码>和代码> B/COD>)的操作交织:


如果您使用该交错处理这些操作,您将看到您丢失了对
x
的计数。这对于
c.y来说已经足够了,这不是重新排序的证据。事实上,所发生的事情是
++
上的
易失性
不是原子的结果。例如,在更新一个变量时,考虑以下两个线程(<代码> A<代码/代码>和代码> B/COD>)的操作交织:


如果您使用该交错处理这些操作,您将看到您丢失了对
x
的计数。对于
c.y来说,这已经足够了。你能提供一个例子说明B>A的可能性吗?在上面描述的流程中,对A的赋值发生在对B的赋值之前。1)变量是
x
y
<代码>A
B
表示螺纹。2) 需要做的是,您在
x
上丢失的计数比在
y
上丢失的计数更多,然后
y感谢您的更新!现在对我来说有点干净了。Stephen,现在我正在运行相同的代码,但在test()上使用synchronized关键字。当volatile在y或x和y上时,它工作正常,但在没有volatile的情况下失败(这是预期的),当volatile仅在x上时失败。这是正常的行为吗?如果你知道发生了什么,请解释一下。这是正常的。当您访问一个非易失性变量而不在互斥锁中访问它时,您可能会看到该变量的一个过时值。您能否提供一个示例,说明B>a是如何可能的?在上面描述的流程中,对A的赋值发生在对B的赋值之前。1)变量是
x
y
<代码>A
B
表示螺纹。2) 需要做的是,您在
x
上丢失的计数比在
y
上丢失的计数更多,然后
y感谢您的更新!现在对我来说有点干净了。Stephen,现在我正在运行相同的代码,但在test()上使用synchronized关键字。当volatile在y或x和y上时,它工作正常,但在没有volatile的情况下失败(这是预期的),当volatile仅在x上时失败。这是正常的行为吗?如果你知道发生了什么,请解释一下。这是正常的。当您访问非易失性变量而不在互斥锁中访问时,您可能会看到该变量的过时值。
public class Client {
    volatile int x;
    volatile int y;
    public void test() {
        x++;
        y++;
    }
    public static void main(String[] args) {
        Client c = new Client();
        while(c.y <= c.x) new Thread(() -> c.test()).start();
        System.out.println(c.x + " " + c.y);
    }
}
thread A: load x -> temp
thread B: load x -> temp
thread A: temp = temp + 1
thread B: temp = temp + 1
thread A: save temp -> x
thread B: save temp -> x