0

CountDownLatch in java is a high-level synchronization utility which is used to prevent a particular thread to start processing until all threads are ready.

But, Semaphore can totally do the same thing. So, what's the merit of CountDownLatch?

One more question: If CountDownLatch do have some merits, Why It was designed to used only once? I think it's easy to add a set method to reset the count.

Ravindra babu
  • 37,698
  • 11
  • 250
  • 211
expoter
  • 1,622
  • 17
  • 34
  • Even I though to mark this question as duplicate but due to second query, I did not do it > Why It was designed to used only once? I think it's easy to add a set method to reset the count. – Ravindra babu Sep 02 '16 at 07:14

3 Answers3

6

Semantically, they're different; and that matters, because it makes your code easier to read. When I see a Semaphore, I immediately start thinking "a limited amount of a shared resource." When I see a CountDownLatch, I immediately start thinking "a bunch of threads waiting for the 'go!' signal." If you give me the former in code that actually needs the latter, it's confusing.

In this sense, a Semaphore being used as a CountDownLatch is a bit like a garden-path sentence; while technically correct, it leads people astray and confuses them.

In terms of more pragmatic uses, a CountDownLatch is just simpler if that's all you need. Simpler is better!

As for reusing a CountDownLatch, that would complicate its usage. For instance, let's say you're trying to queue up threads A, B, and C for some work. You have them await on the latch, and then you release it. Then you reset it, presumably to queue up threads D, E and F for some other work. But what happens if (due to a race condition), thread B hasn't actually been released from the first latch yet? What if it hadn't even gotten to the await() call yet? Do you close the gate on it, and tell it to wait with D, E and F for the second opening? That might even cause a deadlock, if the second opening depends on work that B is supposed to be doing!

I had the same questions you did about resetting when I first read about CountDownLatch. But in practice, I've rarely even wanted to reset one; each unit of "wait then go" (A-B-C, then D-E-F) naturally lends itself to creating its own CountDownLatch to go along with it, and things stay nice and simple.

yshavit
  • 42,327
  • 7
  • 87
  • 124
  • Thanks, and why It was designed to used only once? – expoter Sep 02 '16 at 07:12
  • @expoter Because there are other classes that allow reuse. Read the [javadoc](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CountDownLatch.html): *This is a one-shot phenomenon -- the count cannot be reset. If you need a version that resets the count, consider using a [`CyclicBarrier`](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CyclicBarrier.html).* – Andreas Sep 02 '16 at 07:15
5

A Semaphore with n blocks when 0 is reached.

A CountDownLatch of n blocks till 0 is reached. Then all continue at approximately the same time.

So a semaphore is like a gate keeper at the disco, and a count down latch like a start shot at game courses.

Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
  • 1
    @expoter If you create a `Semaphore` with N *permits*, you can [`acquire()`](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Semaphore.html#acquire--) N times, and call number N+1 to `acquire()` will block, i.e. it will only block *when* the permit count reaches zero. --- If you create a `CountDownLatch` with a count of N, any call to [`await()`](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CountDownLatch.html#await--) will block *until* the count reaches zero, i.e. N calls to `countDown()`. --- Totally different functionality. – Andreas Sep 02 '16 at 07:23
  • 1
    +1 (and I agree with @Andreas), but as a small note: `semaphore.acquire(0)` will still block until there are at least 0 permits, and a semaphore is allowed to have a negative number of permits, so it's actually fairly easy to use a Semaphore as basically a "CountUpLatch" (counting from -numberOfCounts to 0). – yshavit Sep 02 '16 at 07:25
  • @Andreas indeed; is my formulation too unclear? Or are you reformulating a bit more clear and in technical detail? – Joop Eggen Sep 02 '16 at 07:53
  • @JoopEggen OP had commented that he didn't understand, so I clarified. That comment is now gone. – Andreas Sep 02 '16 at 07:54
  • @yshavit a Semaphore is indeed a kind of anti-matter CountDownLatch, unfortunately not only a negative number of permits must be possible, but acquire would need to increase, or release would need to block. But it is good to have a view for such concepts. – Joop Eggen Sep 02 '16 at 08:02
  • I'm not sure what you mean by that. If you create the Semaphore with -3 permits (which you can do), then any number of calls to acquire(0) will block until you call release() 3 times. – yshavit Sep 02 '16 at 08:09
  • So every thread (that has to start simultaneously) calls release + acquire? Sorry @yshavit, I am now deeply involved in another DB related issue, so you may be entirely right. Thanks for the feedback. – Joop Eggen Sep 02 '16 at 10:39
  • No, that's not what I meant. Just a very simple substitution: countDown() turns into release(), and await() turns into acquire(0). So simple a regex could do it. :) – yshavit Sep 02 '16 at 12:58
  • @yshavit aha, okay. – Joop Eggen Sep 02 '16 at 13:57
1

Semaphore can totally do the same thing. So, what's the point of CountDownLatch?

Semaphore maintains a set of permits. Each acquire() blocks if necessary until a permit is available, and then takes it. Each release() adds a permit, potentially releasing a blocking acquirer.

However, no actual permit objects are used; the Semaphore just keeps a count of the number available and acts accordingly.

Semaphore is blocking the entry to enter critical section and CountDownLatch is blocking the execution of main thread unless other threads complete their tasks.

Have a look at this SE question for more details:

CountDownLatch vs. Semaphore

If CountDownLatch do have some points, Why It was designed to used only once?

If you want to use it repeatedly, use CyclicBarrier

A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point. CyclicBarriers are useful in programs involving a fixed sized party of threads that must occasionally wait for each other. The barrier is called cyclic because it can be re-used after the waiting threads are released.

Javadocs of CountDownLatch quote that :

A CountDownLatch is a one-shot phenomenon -- the count cannot be reset. If you need a version that resets the count, consider using a CyclicBarrier.

Community
  • 1
  • 1
Ravindra babu
  • 37,698
  • 11
  • 250
  • 211