我试图调查在java环境中重新排序(使用JDK 9-ea + 170)的行为,并发现我无法为自己解释的一件事,所以我很乐意听到关于它的一些说明。下面是一个例子:为什么使用两个volatile变量重新排序?
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);
}
}
这个方案有一个test()
方法,该方法只是增加x和y值。我正在创建新的线程,并调用此test()
,直到某些内部java优化不会更改x++; y++;
指令()的顺序。这样我证明重新排序确实发生。程序大部分时间结束(这是预期的)。 现在我已经加入volatile修饰符到Y:
public class Client {
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);
}
}
这个程序永远不会结束,因为挥发性保证了所有的前挥发的指令会被冲入所以x++;
总是y++;
之前执行的内存,这是不可能有y> x。这也是我的理解所期待的。但在那之后我已经添加挥发性到int 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);
}
}
为什么这里的重新排序也发生?
能否请您提供一个例子怎么可能是B> A? 在上面描述的流程中,赋值给A发生在赋值给B之前。 –
1)变量是'x'和'y'。 'A'和'B'表示线程。 2)所有需要发生的事情是,你在'x'上的损失比在'y'上损失更多,然后'y <= x'将会是'false'。 –
感谢您的更新!现在对我来说有点干净了。斯蒂芬,现在我运行相同的代码,但在test()上使用同步关键字。它在volatile或y和x和y上工作正常,但在没有volatile的情况下(这是预期的)失败并且仅在x上volatile时失败。这是正常的行为吗?请解释你是否知道发生了什么 –