1

While running each thread why does the countdown.getCount() always print '3' even after the previous thread has already called countdown.countDown() and reduced the Latch Count by 1?

I am kind of worndering how Java knows that the Latch Count has reached 0, so that it can release all the 3 threads.

import java.util.concurrent.CountDownLatch;

class b {
static final CountDownLatch countdown = new CountDownLatch(3);

public static void main(String[] args) {

    for (int i = 0; i < 3; ++i) {
        Thread t = new Thread() {
            public void run() {
                System.out.printf("Starting on %d other threads.\n",
                        countdown.getCount());
                countdown.countDown();
                System.out.printf("new on %d other threads.\n",
                        countdown.getCount());
                try {
                    countdown.await(); // waits until everyone reaches this
                                        // point
                    // System.out.println("Go again : "
                    // +countdown.getCount());
                } catch (Exception e) {
                }
            }
        };
        t.start();

    }
    System.out.println("Go");
}

}

user547453
  • 1,035
  • 6
  • 22
  • 38
  • The logical error is in *"after the previous thread has already called countdown.countDown()"*: it probably hasn't – assylias Nov 27 '12 at 20:13
  • 2
    http://ideone.com/EloGi9 - works fine there. If you are lucky it behaves like you expected. That's the beauty of undefined multthreading behavior – zapl Nov 27 '12 at 20:15

2 Answers2

2

you are starting 3 threads in parallel. depending on how fast they start, they could all print "3" before any of the threads manages to call countDown() (at least for the "Starting on..." line). the "new on ..." line, however, should print out some range of numbers between 2 and 0.

jtahlborn
  • 52,909
  • 5
  • 76
  • 118
  • well if it all starts together then how does Java know (update the latch count) the threads can be released from waiting? – user547453 Nov 27 '12 at 23:19
  • @user547453 - i'm confused by your question. the `await()` call returns when the latch reaches 0. that will be as soon as all of the threads have called `countDown()`. – jtahlborn Nov 28 '12 at 00:58
0

It's absolutely possible that all three threads print "Starting on 3.." as the threads run in parallel, and the count doesn't change until a thread executed countDown(). To really understand what's going on, I suggest you prepend System.nanoTime() and thread name before your print statements as below:

...
Thread t = new Thread("Thread-" + i) { 
...
System.out.printf("%d> %s: Starting on %d other threads.\n", System.nanoTime(), getName(), countdown.getCount());
countdown.countDown();
System.out.printf("%d> %s: new on %d other threads.\n", System.nanoTime(), getName(), countdown.getCount());

Sometimes you'd get an output like below which may give you the impression that Thread-2 is disregarding Thread-1's call to countDown:

1407489646569321000> Thread-0: Starting on 3 other threads.
1407489646569324000> Thread-1: Starting on 3 other threads.
1407489646602463000> Thread-1: new on 1 other threads.
1407489646569513000> Thread-2: Starting on 3 other threads.
1407489646602107000> Thread-0: new on 2 other threads.
1407489646603275000> Thread-2: new on 0 other threads.

However, that is not the case, and we can verify the correct order of operations by looking at the timestamp. The mixup in the output is due to inherent unpredictability in thread scheduling, depending on which thread gets the cpu splice.

Having said that, they may not always print 3, depending on thread scheduling or delays. As an example, try putting a Thread.sleep(..) as shown below:

public static void main(String[] args) throws Exception {
    for (int i = 0; i < 3; ++i) {
        Thread t = new Thread() {
            public void run() {
                 /* As before */
            }
        };
        t.start();
        Thread.sleep(100); // Artificial Delay
    }
}

Now you should see different results like below:!

1407490223575404000> Thread-0: Starting on 3 other threads.
1407490223607879000> Thread-0: new on 2 other threads.
1407490223676233000> Thread-1: Starting on 2 other threads.
1407490223676818000> Thread-1: new on 1 other threads.
1407490223777623000> Thread-2: Starting on 1 other threads.
1407490223778221000> Thread-2: new on 0 other threads.

Internally, the CountDownLatch maintains a first in, first out wait Queue (See. AbstractQueuedSynchronizer). The value of the count is synchronized, and the waiting threads are only released when the count becomes 0 or someother thread interrupts the waiting thread. This is the mechanism used by the latch to keep track of when all the threads have arrived at the latch.

If you're interested in understanding the latch in the context of testing, checkout http://razshahriar.com/2014/08/testing-asynchronous-code-in-java-with-countdownlatch/ Hope this helps clarify your investigation of the Program behaviour.

Raz
  • 860
  • 1
  • 9
  • 12