问题描述
您忘了声明@H_404_3@guard为易失性布尔值。
如果您将字段声明省略为@H_404_3@volatile,则不会告诉JVM该字段可以被多线程看到,例如您的示例。
在这种情况下,的值@H_404_3@guard将被读取一次,并且将导致无限循环。它将针对以下内容进行优化(无打印):
@H_404_3@if(!guard) { while(true) { } }
现在为什么要@H_404_3@System.out.println改变这种行为?因为@H_404_3@writes是同步的,这迫使线程不缓存读取。
这里粘贴了@H_404_3@println一种@H_404_3@PrintStream使用的方法的代码@H_404_3@System.out.println:
@H_404_3@public void println(String x) { synchronized (this) { print(x); newLine(); } }
@H_404_3@private void write(String s) { try { synchronized (this) { ensureOpen(); textOut.write(s); textOut.flushBuffer(); charOut.flushBuffer(); if (autoFlush && (s.indexOf('\n') >= 0)) out.flush(); } } catch (InterruptedioException x) { Thread.currentThread().interrupt(); } catch (IOException x) { trouble = true; } }
注意同步。
解决方法
public class GuardedBlock {
private boolean guard = false;
private static void threadMessage(String message) {
System.out.println(Thread.currentThread().getName() + ": " + message);
}
public static void main(String[] args) {
GuardedBlock guardedBlock = new GuardedBlock();
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
guardedBlock.guard = true;
threadMessage("Set guard=true");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
threadMessage("Start waiting");
while (!guardedBlock.guard) {
//threadMessage("Still waiting...");
}
threadMessage("Finally!");
}
});
thread1.start();
thread2.start();
}
}
我正在通过Java Essentials教程学习并发性。找到了守卫的方块并尝试对其进行测试。我无法理解的一件事。
虽然循环是无限的,但是如果您取消注释threadMessage行,则一切正常。为什么?