1

In general, I want to block the provider of a blocking queue until the queue becomes empty, and then put a batch of elements into the queue.

I find a relative question here:

How to block until a BlockingQueue is empty?

However I'm still confused.

my current implementation is like (pseudo code):

BlockingQueue blockingQueue = new BlockingQueue();
// provider code
while (true) {
    // wait until the blocking queue becomes empty
    synchronized (blockingQueue) {
    while (!blockingQueue.isEmpty()) {
        blockingQueue.wait();
        }
    }

    // put a batch of elements into blocking queue
    List<Element> elementList = getSomeElements();
    for (Element element : elementList) {
        blockingQueue.put(element)
    }
}

// consumer code
while (true) {
    // take a element
    blockingQueue.take();

    // if the blocking queue becomes empty, notify the provider
    synchronized (blockingQueue) {
        if (blockingQueue.isEmpty()) {
            blockingQueue.notify();
        }
    }
}

The code seems to be OK, but I still doubt that it is not thread-safe, and may lead to dead-lock condition.

Is my implementation thread-safe? Is there any better way to do this?

liubenxi
  • 91
  • 9
  • 1
    This code is not thread safe. You are waiting for a condition in a `synchronized` block, but then leaving the `synchronized` block before taking action. There is no guaranty that the condition stays true when you have left the `synchronized` block. Besides that, the name “`blockingQueue`” suggests that you are mixing two different synchronization mechanisms. This is a recipe for a deadlock, as explained in [this comment](https://stackoverflow.com/questions/15184943/how-to-block-until-a-blockingqueue-is-empty#comment78079219_15185004) on the Q&A you’ve already linked. – Holger Jun 28 '19 at 11:06
  • @Holger yes I agree with that the code is not thread safe. But will it cause deadlock? The code snippet is a bit different from the code in the [previous question](https://stackoverflow.com/a/15185004/3530379). The deadlock should only happen when the provider waits for a notify that will never come. I still don't understand how to reach such a state. – liubenxi Jun 28 '19 at 12:12
  • 1
    By moving the blocking operation out of the `synchronized` block, you destroyed the thread safety. Bringing it back by moving the blocking operations into the `synchronized` block will make it subject to deadlocks again. In either case, mixing different synchronization mechanisms leads to problems. – Holger Jun 28 '19 at 14:18
  • instead of using a BlockingQueue you could also consider using a `Phaser` https://www.baeldung.com/java-phaser – Maurice Apr 18 '23 at 02:49

0 Answers0