【问题标题】:Producer-Consumer Logging service with Unreliable way to shutdown具有不可靠关闭方式的生产者-消费者日志服务
【发布时间】:2015-07-26 14:16:05
【问题描述】:

我正在阅读“实践中的 Java 并发”,其中一个示例让我感到困惑,它是关于生产者-消费者日志服务的:

public class LogWriter {
    private final BlockingQueue<String> queue;
    private final LoggerThread logger;
    private boolean shutdownRequested = false;
    public LogWriter(Writer writer) {
        this.queue = new LinkedBlockingQueue<String>(CAPACITY);
        this.logger = new LoggerThread(writer);
    }
    public void start() { logger.start(); }
    public void shutdownlog() { shutdownRequested = true; }
    public void log(String msg) throws InterruptedException {
        if (!shutdownRequested)
            queue.put(msg);
        else
            throw new IllegalStateException("logger is shut down");
    }
    private class LoggerThread extends Thread {
        private final PrintWriter writer;
        ...
        public void run() {
            try {
                while (true)
                   writer.println(queue.take());
            } catch(InterruptedException ignored) {
            } finally {
                writer.close();
            }
        } 
    }
}

从书中看,如果我们关闭它是不可靠的。它写道:

另一种关闭 LogWriter 的方法是设置一个“已请求关闭”标志以防止提交更多消息,如清单 7.14 所示。然后,消费者可以在收到关闭已通知的通知后清空队列被请求,写出任何挂起的消息并解除阻塞日志中阻塞的任何生产者。但是,这种方法存在竞争条件,使其不可靠。 log 的实现是一个 checkthenact 序列:生产者可以观察到服务尚未关闭,但关闭后仍然排队消息,同样存在生产者可能在 log 中被阻塞并且永远不会出现的风险变得畅通无阻。有一些技巧可以降低这种可能性(比如让消费者在宣布队列耗尽之前等待几秒钟),但这些不会改变根本问题,只会改变它导致失败的可能性。

我不太明白。这是否意味着另一个线程恰好在shutdownflag设置为true之后遇到了queue.put(msg)?

谢谢各位。

【问题讨论】:

  • 不应该是线程循环中的while(!shutdownRequested) 吗?更不用说布尔值对于多线程使用必须是可变的。
  • @the8472,我想我们不应该在消费者循环中使用 !shutdownRequested 。消费者一直在不断地运行,试图完成从队列中取出项目的工作。对于易失性,我完全同意你的看法:)

标签: java multithreading concurrency producer-consumer


【解决方案1】:

漏洞在生产者通过检查shutdownRequested检查标志然后将消息放入队列之间。如果关闭发生并且工作人员在这个微小的时间跨度内停止执行,就会发生这种情况。 虽然不太可能,但您可能会在已设置标志时将消息排入队列。

但我看不到生产者被阻止,因为工人只是忽略了关闭标志。

如果生产者在队列已满时尝试将消息入队,则会阻塞,但当工作人员从队列中取出元素时,它会变得畅通。

【讨论】:

  • 我同意你的看法。我也看不到制作人被阻止。谢谢大佬。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-21
  • 1970-01-01
  • 2019-05-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多