我正在阅读 Java 并发实践并遇到以下代码片段(清单 7.15.向 LogWriter 添加可靠的取消。)。
public class LogService {
private final BlockingQueue<String> queue;
private final LoggerThread loggerThread;
private final PrintWriter writer;
@GuardedBy("this") private boolean isShutdown;
@GuardedBy("this") private int reservations;
public void start() { loggerThread.start(); }
public void stop() {
synchronized (this) { isShutdown = true; }
loggerThread.interrupt();
}
public void log(String msg) throws InterruptedException {
synchronized (this) {
if (isShutdown)
throw new IllegalStateException(...);
++reservations;
}
queue.put(msg);
}
private class LoggerThread extends Thread {
public void run() {
try {
while (true) {
try {
synchronized (LogService.this) {
if (isShutdown && reservations == 0)
break;
}
String msg = queue.take();
synchronized (LogService.this) {
--reservations;
}
writer.println(msg);
} catch (InterruptedException e) { /* retry */ } // interruption policy
}
} finally {
writer.close();
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
为什么作者不在isShutdownand上使用 volatile reservations?LoggerThread 可能会缓存它们并使用它们自己的副本我在哪里有错误?
这两个变量都是在块中独占访问的synchronized。这可以防止多个线程同时访问变量,并强制执行先行发生关系,以确保跨线程更改的可见性。
当临界区包含多个操作时,将该临界区涉及的变量声明为 易失性是不够的,因为其他线程仍然可以在具有易失性变量的操作之间进行抢占。
| 归档时间: |
|
| 查看次数: |
48 次 |
| 最近记录: |