在图形类中,我有它,所以当你按“m”时它会使布尔值为M,然后我就有了这段代码。
graphic.m = false;
while(graphic.m == false){
}
graphic.m = false;
它不起作用,它不会在它之前继续使用代码。
但如果我这样做
graphic.m = false;
while(graphic.m == false){
System.out.println("m");
}
graphic.m = false;
它完美地运作,有人可以解释为什么以及如何通过这个?
答案 0 :(得分:3)
为了实现这一目标,其他一些主题必须将graphic.m
设置为true
。所以我认为这种情况正在发生。
我的猜测是graphic.m
不是一个易变的字段。这意味着在写入它的一个线程(从另一个线程将其设置为true
)与从中读取的另一个线程(您拥有的代码)之间没有正式发生的关系。 JVM可以自由地在线程中缓存值(或让CPU核心缓存它们等),并且似乎正在这样做。
System.out.println
是一种同步方法。即使根据JLS对graphic.m
没有任何形式上的影响,发布/获取同步锁的行为很可能会在内核之间刷新内存,这样你的线程就会看到{{1}最近的价值。要强调:这不是有发生的Java规范,你不应该依赖于这种行为 - 如果你这样做,你可能会被一个难以接受的东西咬伤捕获JVM的某些未来版本中的错误,或稍微不同的硬件等。
解决方案是使graphic.m
成为graphic.m
字段(或通过同步方法获取/设置它,或使用AtomicBoolean)。
答案 1 :(得分:0)
您需要包含volatile
关键字,以确保跨线程可见变量的可见性。
当线程对非易失性变量进行操作时,每个变量都可能会在处理它们时将这些变量从主内存复制到自己的CPU缓存中。对于非易失性变量,JVM不保证它将从主存储器或CPU高速缓存读取数据,或者它将从CPU高速缓存写回主存储器。
如果声明变量volatile
,JVM会确保所有读取都来自主内存,所有写入也都是主内存。
System.out
可能有助于刷新CPU缓存。它是一种同步方法,所以我认为它的锁定会给JVM时间。