您遇到的问题是,您没有足够长的时间来优化代码并缓存值。
当x86_64系统上的线程第一次读取值时,它将获得线程安全副本。它只能在以后的变化中看不到。其他CPU可能不是这种情况。
如果您尝试此操作,则可以看到每个线程都卡住了其本地值。
public class RequiresVolatileMain {
static volatile boolean value;
public static void main(String... args) {
new Thread(new MyRunnable(true), "Sets true").start();
new Thread(new MyRunnable(false), "Sets false").start();
}
private static class MyRunnable implements Runnable {
private final boolean target;
private MyRunnable(boolean target) {
this.target = target;
}
@Override
public void run() {
int count = 0;
boolean logged = false;
while (true) {
if (value != target) {
value = target;
count = 0;
if (!logged)
System.out.println(Thread.currentThread().getName() + ": reset value=" + value);
} else if (++count % 1000000000 == 0) {
System.out.println(Thread.currentThread().getName() + ": value=" + value + " target=" + target);
logged = true;
}
}
}
}
}
打印下面显示其fliling值,但卡住了。
Sets true: reset value=true
Sets false: reset value=false
...
Sets true: reset value=true
Sets false: reset value=false
Sets true: value=false target=true
Sets false: value=true target=false
....
Sets true: value=false target=true
Sets false: value=true target=false
如果我添加-XX:+PrintCompilation
此开关发生了时间,你看到
1705 1 % RequiresVolatileMain$MyRunnable::run @ -2 (129 bytes) made not entrant
1705 2 % RequiresVolatileMain$MyRunnable::run @ 4 (129 bytes)
这表明代码已经被编译为本地是不是线程安全的方式。
,如果你让volatile
你看到它不断地翻转值的值(或直到我厌倦)
编辑:这是什么做的测试是;当它检测到的值不是那个线程目标值时,它设置该值。即。线程0设置为true
,线程1设置为false
当两个线程正确共享字段时,他们会看到对方发生更改,并且值不断在true和false之间翻转。
没有volatile会失败,每个线程只能看到它自己的值,所以它们都改变了值,线程0看到true
,线程1看到false
为同一个字段。
简短的回答没有。但是你真的需要检查在有人告诉你之后从屋顶跳下是否危险,并给出了充分的理由吗? – Voo
使用2芯电脑。 –
@Voo ...你到底在说什么? –