3

I am trying to create a deadlock using join in threads (JAVA). According to my understanding the below program should terminate. Can somebody please explain why the below program doesn't terminate?

public class DeadLockUsingJoins2 {

    public static void main(String[] args) {

        AThread a = new AThread(null, "A");
        a.start();
        AThread b = new AThread(a, "B");
        b.start();
        a.t = b;
    }
}

class AThread extends Thread{

    public Thread t;

    public AThread(Thread thread, String name){
        super(name);
        this.t = thread;
    }

    @Override
    public void run(){
        try {
            if(t != null)
                t.join();
            else
            {
                Thread.sleep(5000);
            }
          //  if(t != null)
          //      t.join();
        } catch (InterruptedException e) {           
            e.printStackTrace();
            System.out.println("Somebody interruped thread - " + this.getName());
        }
        System.out.println("Winding Up thread - " + this.getName());
    }

}
4
  • I haven't read the code yet, but I thought the entire idea of a "deadlock" is when 2 threads compete for a resource and both never get it so the program doesn't terminate. Commented Apr 11, 2013 at 9:18
  • AThread b = new AThread("A", "B"); Commented Apr 11, 2013 at 9:18
  • thread 'B' waits for 'A' to terminate. As soon as 'A' terminates (which happens after sleep), 'B' should also terminate. Isn't it? Commented Apr 11, 2013 at 9:23
  • This just works fine.. I do not see any reason why it wont terminate.. Commented Apr 11, 2013 at 9:24

5 Answers 5

3

The only reason i see for not terminating is that your main thread reaches the line

a.t = b;

before thread "a" reaches the lines

if(t != null)
    t.join();

if so, the threads wait for each other to terminate.

To make sure you get a deadlock - your class names suggests this - you should reorder your main method:

public static void main(String[] args) {
    AThread a = new AThread(null, "A");
    AThread b = new AThread(a, "B");
    a.t = b;
    a.start();
    b.start();
}
Sign up to request clarification or add additional context in comments.

1 Comment

@ Marco Forber - Thanks. Simply this is what I intend to do.
2

add a pause before a.t = b;

    b.start();
    Thread.sleep(100);
    a.t = b;

it will work. But to be reliable it needs syncronization, eg like this

public class DeadLockUsingJoins2 {
    public static boolean go;

    public synchronized static void main(String[] args)
            throws InterruptedException {
        AThread a = new AThread(null, "A");
        AThread b = new AThread(a, "B");
        a.start();
        while (!go) {
            DeadLockUsingJoins2.class.wait();
        }
        a.t = b;
        b.start();
        DeadLockUsingJoins2.class.notifyAll();
    }
}

class AThread extends Thread {
    public Thread t;

    public AThread(Thread thread, String name) {
        super(name);
        this.t = thread;
    }

    @Override
    public void run() {
        try {
            if (t != null)
                t.join();
            else {
                synchronized (DeadLockUsingJoins2.class) {
                    DeadLockUsingJoins2.go = true;
                    DeadLockUsingJoins2.class.notifyAll();
                }
                Thread.sleep(5000);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Winding Up thread - " + this.getName());
    }

2 Comments

Well, it will probably work for most of the time, but it's not 100% reliable. it's also slowing down the app. I'd use a true synchronization instead.
@david I agree, my purpose was to give a hint why it hangs, now added synchronization
2

It will deadlock if main thread is executed up to a.t = b; before run() on any of the created threads is actually called. The threads then deadlock on join() calls.

EDIT: To avoid this, you need to use some sort of synchronization between the main thread and the threads you're creating. For example, signal the start of run() using Object.notify() and wait for that using Object.wait() in main thread.

1 Comment

"before run() on any of the created threads is actually called" - Actually in this example we are not so concerned about thread 'B' right. Because anyways its going to wait on 'A'
1

So you have successfully written a deadlock, because each of your threads is waiting for the other.

Because the thread run method never finish.

1 Comment

Can you please explain more as to why run() never finishes. According to my understanding thread 'B' is waiting for 'A'. While 'A' just sleeps for 5 secs and should finish, which should be followed by 'B'. After dry run, I thought this code is incomplete for deadlock, but looks otherwise. Thats what I dont understand.
1

Most of the time it terminates. The problem appears when thread B starts running (but doesn't pass the if(t != null) check) after making a.t = b.

When this is the case both threads waits one for the other to finish because of the join inside.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.