Producer-Consumer Logging service with Unreliable way to shutdown

旧巷老猫 提交于 2019-12-11 04:00:10

问题


I'm reading 'Java Concurrency in Practice', one example sort of makes me confused, it's about producer-consumer logging service:

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();
            }
        } 
    }
}

From the book, it's unreliable if we would shutdown it. It wrote:

Another approach to shutting down LogWriter would be to set a "shutdown requested" flag to prevent further messages from being submitted,as shown in Listing7.14.The consumer could then drain the queue upon being notified that shutdown has been requested, writing out any pending messages and unblocking any producers blocked in log. However, this approach has race conditions that make it unreliable. The implementation of log is a checkthenact sequence: producers could observe that the service has not yet been shut down but still queue messages after the shutdown,again with the risk that the producer might get blocked in log and never become unblocked. There are tricks that reduce the likelihood of this (like having the consumer wait several seconds before declaring the queue drained), but these do not change the fundamental problem, merely the likelihood that it will cause a failure.

I don't quite understand it. does it mean that another thread happens to run into queue.put(msg) right after the shutdownflag set to true?

Thanks, guys.


回答1:


The loophole is between the producer checking the flag by checking shutdownRequested and then putting the message in the queue. If shutdown happens and the worker stops performing in this tiny timespan, this happens. Although its unlikely, it might happen that you enqueue messages when flag is already set.

But I cant see that the producer getting blocked, because the worker simply ignores the shutdown flag.

If the producer tries to enqueue a message while the queue is full it blocks, but becomes unblocked when the worker takes elements from the queue.



来源:https://stackoverflow.com/questions/31626772/producer-consumer-logging-service-with-unreliable-way-to-shutdown

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!