Java并发实践“清单7.15”。为什么isShutdown和保留不是易失性的?

1 java concurrency

我正在阅读 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 可能会缓存它们并使用它们自己的副本我在哪里有错误?

Bur*_*dar 5

这两个变量都是在块中独占访问的synchronized。这可以防止多个线程同时访问变量,并强制执行先行发生关系,以确保跨线程更改的可见性。

当临界区包含多个操作时,将该临界区涉及的变量声明为 易失性是不够的,因为其他线程仍然可以在具有易失性变量的操作之间进行抢占。