aknon
aknon

Reputation: 1458

Is this an Improper use of CountdownLatch with initial count = 1

Below is the snippet, listing 5.11 from book 'java concurrency in practice' by Brain Goetz.

I find the below code confusing. It seems that countdownlatch 'startGate' has a flawed usage. ( 'endGate' usage is OK )

public class TestHarness {
public long timeTasks(int nThreads, final Runnable task)
        throws InterruptedException {
    final CountDownLatch startGate = new CountDownLatch(1);
    final CountDownLatch endGate = new CountDownLatch(nThreads);
    for (int i = 0; i < nThreads; i++) {
        Thread t = new Thread() {
            public void run() {
                try {
                    startGate.await();
                    try {
                        task.run();
                    } finally {
                        endGate.countDown();
                    }
                } catch (InterruptedException ignored) {
                }
            }
        };
        t.start();
    }
    long start = System.nanoTime();
    startGate.countDown();
    endGate.await();
    long end = System.nanoTime();
    return end - start;
}

}

Execution of line startGate.countDown() will notify all the worker threads waiting on the latch. But is this guaranteed to notify all the nThreads ?
It is quite possible only a few threads, say 2 threads, out nTheads have executed startGate.await() call of the run() method.
And at this time the main thread executes startGate.countDown(). This call will notify only the 2 threads ( out of nThreads ) waiting on the latch.

Now the rest of the other threads ( nThread - 2 ) will call startGate.await() later in time, but as the main thread has already raised a notification, so the worker threads( nThreads- 2) will now wait indefinitely for notification ?

Or I am missing something ?

Upvotes: 1

Views: 1966

Answers (3)

aknon
aknon

Reputation: 1458

Thanks to answers from @Brain and @Narendra. Having just gone through the source code of CountDownLatch and AbstractQueuedSynchroniser classes, I would like to add some more details.

It is not a wait() and notify() based system, which I had mistakenly assumed because of the CountdownLatch.await()method.

  • CountdownLatch.countDown() : If current count equals 0 , then it does nothing and simply returns. Otherwise, it first decreases the count by 1, and then checks if it 0. If 0 then it releases 'shared'.

  • CountdownLatch.await() : Checks for the current count, if it equals 0 ( may be interrupted in between ), then it does nothing and simply returns. This method acquires 'shared' only when count > 0 ( or is not interrupted ).

It also appears that a declaration like latch = new CountDownLatch(0), though harmless, but would be a worthless declaration, and should raise an Exception right in the constructor code, as it does for count < 0.

Upvotes: 0

Brian Roach
Brian Roach

Reputation: 76908

Once startGate.countDown(); is called the count is zero (because it started at one). Any subsequent calls to startGate.await(); ... don't wait; it's been counted down to zero.

From the Javadocs for CountDownLatch.await():

If the current count is zero then this method returns immediately.

A CountDownLatch is used to block threads only until some work in another thread(s) is completed. Once that work is completed, the latch is counted down to zero allowing any waiting or future threads to continue past it.

Upvotes: 3

Narendra Pathai
Narendra Pathai

Reputation: 41945

The CountDownLatch countDown() is not like a notification that can be missed but is like a Gate. So once the gate is open it is open any time after. So the other threads which call await() will be directly allowed and not block.

Upvotes: 1

Related Questions