Search code examples
javamultithreadingconcurrencycyclicbarrier

Application hangs when I invoke join inside CyclicBarrier callback


I have the following method test where I start threads:

public static void main(String[] args) throws InterruptedException {
        List<Thread> threads = new ArrayList<>();
        final CyclicBarrier cyclicBarrier = new CyclicBarrier(1);
        Thread thread = new Thread(new CallbackThread(cyclicBarrier, threads));
        threads.add(thread);
        thread.start();          
    }

CallBack thread looks like this:

class CallbackThread implements Runnable {
    CyclicBarrier cyclicBarrier;
    List<Thread> threads;

    CallbackThread(CyclicBarrier cyclicBarrier, List<Thread> threads) {
        this.cyclicBarrier = cyclicBarrier;
        this.threads = threads;
    }

    @Override
    public void run() {
        try {
            cyclicBarrier.await();
        } catch (InterruptedException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        } catch (BrokenBarrierException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
        System.out.println("Threads started");
        for (Thread thread1 : threads) {
            try {
                thread1.join();
            } catch (InterruptedException e) {
                e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
            }
        }
        System.out.println("Threads finished");

    }
}

When I run application I see following output:

Threads started

and application hangs.

I don understand why.

If to replace join logic to main method - all goods well.

public static void main(String[] args) throws InterruptedException {
        List<Thread> threads = new ArrayList<>();
        final CyclicBarrier cyclicBarrier = new CyclicBarrier(1);
        Thread thread = new Thread(new CallbackThread(cyclicBarrier, threads));
        threads.add(thread);
        thread.start();
        for (Thread thread1 : threads) {
            try {
                thread1.join();
            } catch (InterruptedException e) {
                e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
            }
        }
        System.out.println("Threads finished");

    }

Can you explain this difference.
IMHO it should work same.


Solution

  • The code from your first example calls join on its own thread. You add it to the list and the thread iterates over the list and joins every thread inside the list.