CountDownLatch vs. Semaphore

Existe alguma vantagem de usar

java.util.concurrent.CountdownLatch

ao invés de

java.util.concurrent.Semaphore?

Tanto quanto eu posso dizer os seguintes fragmentos são quase equivalentes:

1. Semáforo

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();

Exceto que, no caso de # 2, a trava não pode ser reutilizada e, mais importante, você precisa saber antecipadamente quantos encadeamentos serão criados (ou esperar até que todos sejam iniciados antes de criar a trava).

Então, em que situação o trinco pode ser preferível?

questionAnswers(6)

yourAnswerToTheQuestion