2

When running the following code, the 2 start threads will be locked by the CyclicBarrier *object and waiting for the third thread infinitely to be unlocked

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class MainDeadlock {
  public static void main(String[] args) throws InterruptedException {
    final CyclicBarrier c = new CyclicBarrier(3); 
    Runnable r = () -> {
            try {
                c.await();
            } catch (InterruptedException | BrokenBarrierException e) {
                e.printStackTrace();
            }
            System.out.println("Run!");
    };
    new Thread(r).start();
    new Thread(r).start();
}

}

So the 2 started thread are waiting for the third third to resolve this barrier. However, according to the Java API documentation of CyclicBarrier, CyclicBarrier is

A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point

I am confused on how they "wait for each other",

Questions: does "wait for each other" imply a circular wait? If so, how? Strictly speaking, is this a deadlock situation?

Rui
  • 3,454
  • 6
  • 37
  • 70
  • 2
    I really suggest you go and do some further reading about deadlocks. This is not one. Is it a bad use of synchronization aids resulting in all threads waiting indefinitely? Yes. Is that the same as a deadlock? No. – Michael Jul 12 '18 at 15:34
  • This one is more complicated as I don't know the implementation of `CyclicBarrier` – Rui Jul 12 '18 at 15:34

3 Answers3

2

You can think of CyclicBarrier as not knowing about threads at all, per-se. Think of it like this:

  1. The barrier maintains a tally of calls to await().
  2. When await() is invoked, the code blocks (the method does not return), but the barrier increases its tally.
  3. When the tally reaches the parties value given on construction, the tally is reset, and all threads which are blocked in a call to await() are released (i.e. the method returns).

So, in your situation, calls to await() won't return until a third invocation occurs, so your 2 existing threads are effectively stuck. This isn't technically a deadlock as it can be got out of easy enough (by making another call to await()).

The reason it is called cyclic is because, once the tally has been reset and the threads have been released, it can be used again. A typical usage would have the parties set to the number of threads that are going to synchronize on it, and those threads all enter some kind of loop, whereby the barrier is used to ensure that no thread moves on to the next iteration until all other threads have also completed the current iteration.

user31601
  • 2,482
  • 1
  • 12
  • 22
1

With regards to the circular wait condition required for a situation to be considered a deadlock, Wikipedia says:

each process must be waiting for a resource which is being held by another process, which in turn is waiting for the first process to release the resource. In general, there is a set of waiting processes, P = {P1, P2, …, PN}, such that P1 is waiting for a resource held by P2, P2 is waiting for a resource held by P3 and so on until PN is waiting for a resource held by P1.

You have a set of processes P1 and P2. They are waiting for something but they are not waiting for a P3 because no such process exists. So it's not a deadlock for this reason.

It also does not satisfy the following condition:

Hold and wait or resource holding: a process is currently holding at least one resource and requesting additional resources which are being held by other processes.

(emphasis mine). You don't have any processes holding any resources, because a third process does not exist.

Michael
  • 41,989
  • 11
  • 82
  • 128
0

Technically this isn't a deadlock because the two threads that are already at the barrier aren't blocked by each other, they're waiting for this third thread that never arrives.

But the end result is very similar to a deadlock, which could be confusing at first.

The wording is a bit confusing too, because technically at a cyclic barrier with limit n the first n-1 threads are waiting for the nth one.

But the key difference between this and a deadlock is in how you resolve them: a cyclic barrier with too few threads will be resolved by more threads arriving, in a deadlock the only "resolution" is to kill one of the threads already waiting.

biziclop
  • 48,926
  • 12
  • 77
  • 104
  • It isn't really relevant that the end result is similar (`while (true);` has a similar end result...), 'deadlock' has a very specific definition and this does not satisfy it. – Michael Jul 12 '18 at 15:39
  • @Michael Exactly. It is only relevant in that it's one of the sources of confusion in the question. – biziclop Jul 12 '18 at 15:40