112

Is there any advantage of using

java.util.concurrent.CountdownLatch

instead of

java.util.concurrent.Semaphore?

As far as I can tell the following fragments are almost equivalent:

1. Semaphore

final Semaphore sem = new Semaphore(0);
for (int i = 0; i < num_threads; ++ i)
{
  Thread t = new Thread() {
    public void run()
    {
      try
      {
        doStuff();
      }
      finally
      {
        sem.release();
      }
    }
  };
  t.start();
}

sem.acquire(num_threads);

2: CountDownLatch

final CountDownLatch latch = new CountDownLatch(num_threads);
for (int i = 0; i < num_threads; ++ i)
{
  Thread t = new Thread() {
    public void run()
    {
      try
      {
        doStuff();
      }
      finally
      {
        latch.countDown();
      }
    }
  };
  t.start();
}

latch.await();

Except that in case #2 the latch cannot be reused and more importantly you need to know in advance how many threads will be created (or wait until they are all started before creating the latch.)

So in what situation might the latch be preferable?

finnw
  • 47,861
  • 24
  • 143
  • 221

7 Answers7

123

CountDownLatch is frequently used for the exact opposite of your example. Generally, you would have many threads blocking on await() that would all start simultaneously when the countown reached zero.

final CountDownLatch countdown = new CountDownLatch(1);

for (int i = 0; i < 10; ++ i) {
   Thread racecar = new Thread() {    
      public void run() {
         countdown.await(); //all threads waiting
         System.out.println("Vroom!");
      }
   };
   racecar.start();
}
System.out.println("Go");
countdown.countDown();   //all threads start now!

You could also use this as an MPI-style "barrier" that causes all threads to wait for other threads to catch up to a certain point before proceeding.

final CountDownLatch countdown = new CountDownLatch(num_thread);

for (int i = 0; i < num_thread; ++ i) {
   Thread t= new Thread() {    
      public void run() {
         doSomething();
         countdown.countDown();
         System.out.printf("Waiting on %d other threads.",countdown.getCount());
         countdown.await();     //waits until everyone reaches this point
         finish();
      }
   };
   t.start();
}

That all said, the CountDownLatch can safely be used in the manner you've shown in your example.

Lii
  • 11,553
  • 8
  • 64
  • 88
James Schek
  • 17,844
  • 7
  • 51
  • 64
  • 1
    Thanks. So my two examples would not be equivalent if multiple threads could wait on the latch... unless sem.acquire(num_threads); is followed by sem.release(num_threads);? I think that would make them equivalent again. – finnw Oct 08 '08 at 21:27
  • In a sense, yes, as long as every thread called acquire followed by release. Strictly speaking, no. With a latch, all threads are eligible to start simultaneously. With the semaphore, they become eligible one after another (which could result in different thread scheduling). – James Schek Oct 08 '08 at 21:38
  • The Java documentation seems to imply this a CountdownLatch fits well with his example: http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/CountDownLatch.html. Specifically, "A CountDownLatch initialized to N can be used to make one thread wait until N threads have completed some action, or some action has been completed N times." – Chris Morris Feb 21 '13 at 18:48
  • You are right. I will update my answer a bit to reflect that this is these are the most common uses of CountDownLatch that I've seen vs that it is the intended use. – James Schek Feb 21 '13 at 19:50
  • 14
    This answers the question _What's the most frequently use of the CountDownLatch?_ It does not answer to the original question regarding the advantages/differences of using a CountDownLatch over a Semaphore. – Marco Lackovic Apr 24 '13 at 16:45
  • the answer would be better if it provided _any_ advantage to not using semaphore to do the same thing. – Lassi Kinnunen Apr 25 '16 at 09:07
  • Not only can `CountDownLatch` be "safely used" in the OP's manner, but it is actually one of the intended usage scenarios of `CountDownLatch` where `Semaphore` does not fit well, at least semantically. Conceptually, `Semaphore` is for concurrent access to a shared resource, while `CountDownLatch` is for waiting for some task(s) to complete before lifting the latch is to let other threads out/run. – wlnirvana May 19 '21 at 05:35
75

CountDownLatch is used to start a series of threads and then wait until all of them are complete (or until they call countDown() a given number of times.

Semaphore is used to control the number of concurrent threads that are using a resource. That resource can be something like a file, or could be the cpu by limiting the number of threads executing. The count on a Semaphore can go up and down as different threads call acquire() and release().

In your example, you're essentially using Semaphore as a sort of CountUPLatch. Given that your intent is to wait on all threads finishing, using the CountdownLatch makes your intention clearer.

Ravindra babu
  • 37,698
  • 11
  • 250
  • 211
mtruesdell
  • 3,697
  • 3
  • 21
  • 20
37

Short summary:

  1. Semaphore and CountDownLatch serves different purpose.

  2. Use Semaphore to control thread access to resource.

  3. Use CountDownLatch to wait for completion of all threads

Semaphore definition of Semaphore from docs.oracle.com :

A 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.

How does it work?

Semaphores are used to control the number of concurrent threads accessing a resource like a file, network socket etc

Semaphore is initialized with a counter value, which provides maximum permits allowed.

acquire() will decrease number of permits. release() will increase number of permits. At any time, its not possible to have more number of resource owners crossing permissible permit count.

It is useful when you have limited number of resources - it may be number of threads, network sockets , network printers etc.

CountDownLatch definition from Javadocs:

A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.

How does it work?

CountDownLatch works by setting a counter initialized with number of threads. Counter is decremented when a thread complete its execution. When all threads complete the execution, counter will become zero.

CountDownLatch Use cases: by howtodoinjava.com by Lokesh Gupta

  1. Maximum Parallelism
  2. Wait for all threads to complete before start of executing other task
  3. Deadlock detection
Ravindra babu
  • 37,698
  • 11
  • 250
  • 211
6

Say you walked in to golf pro shop, hoping to find a foursome,

When you stand in line to get a tee time from one of the pro shop attendants, essentially you called proshopVendorSemaphore.acquire(), once you get a tee time, you called proshopVendorSemaphore.release().Note: any of the free attendants can service you, i.e. shared resource.

Now you walk up to starter, he starts a CountDownLatch(4) and calls await() to wait for others, for your part you called checked-in i.e. CountDownLatch.countDown() and so does rest of the foursome. When all arrive, starter gives go ahead(await() call returns)

Now, after nine holes when each of you take a break, hypothetically lets involve starter again, he uses a 'new' CountDownLatch(4) to tee off Hole 10, same wait/sync as Hole 1.

However, if the starter used a CyclicBarrier to begin with, he could have reset the same instance in Hole 10 instead of a second latch, which use & throw.

Ravindra babu
  • 37,698
  • 11
  • 250
  • 211
Raj Srinivas
  • 69
  • 1
  • 1
  • 1
    I'm not sure I understand your answer, but if you are attempting to describe how CountdownLatch and Semaphore work, that is not the subject of the question. – finnw Aug 01 '13 at 23:37
  • 13
    Unfortunately I know nothing about golf. – ring bearer May 26 '15 at 06:13
  • but the starter stuff could be just as well be done with .acquire(players) and increasing the relesed count with release. the countdownlatch seems to just have less functionality and no reusability. – Lassi Kinnunen Apr 25 '16 at 09:06
2

Looking at the freely available source, there is no magic in the implementation of the two classes, so their performance should be much the same. Choose the one that makes your intent more obvious.

flup
  • 26,937
  • 7
  • 52
  • 74
Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305
0

CountdownLatch makes threads wait on the await() method, until such a time as the count has reached zero. So maybe you want all your threads to wait until 3 invocations of something, then all the threads can go. A Latch generally can not be reset.

A Semaphore allows threads to retrieve permits, which prevents too many threads from executing at once, blocking if it cannot get the permit(s) it requires to proceed. Permits can be returned to a Semaphore allowing the other waiting threads to proceed.

Spencer Kormos
  • 8,381
  • 3
  • 28
  • 45
0

Semaphore controls access to a shared resource through the use of a counter. If the counter is greater than zero, then access is allowed. If it is zero, then access is denied. Counter is counting the permits that allow access to shared resource. Thus to access the resource, a thread must be granted a permit from the semaphore.

CountDownlatch make a thread to wait until one or more events have occured. A countDownLatch is initially created with a count of the number of events that much occur before the latch is released. Each time an event happens, the count is decremented.

the_code
  • 85
  • 2
  • 10