3

i am going through oracle docs for deadlock.. i found this code

public class Deadlock {
    static class Friend {
        private final String name;
        public Friend(String name) {
            this.name = name;
        }
        public String getName() {
            return this.name;
        }
        public synchronized void bow(Friend bower) {
            System.out.format("%s: %s"
                + "  has bowed to me!%n", 
                this.name, bower.getName());
            bower.bowBack(this);
        }
        public synchronized void bowBack(Friend bower) {
            System.out.format("%s: %s"
                + " has bowed back to me!%n",
                this.name, bower.getName());
        }
    }

    public static void main(String[] args) {
        final Friend alphonse =
            new Friend("Alphonse");
        final Friend gaston =
            new Friend("Gaston");
        new Thread(new Runnable() {
            public void run() { alphonse.bow(gaston); }
        }).start();
        new Thread(new Runnable() {
            public void run() { gaston.bow(alphonse); }
        }).start();
    }
}

I am failing to understand, in what case deadlock will happen?

I run this code, it works fine. So there must be some special event, when deadlock will happen?

Suppose bow is called on alphonse object first, will it leave its lock on alphonse object when bower.bowBack(this) is called on bower object? Because if it retains its lock, bow function on another object will not get lock until alphonse leave its lock, and it will never be a deadlock situation..

Ivaylo Strandjev
  • 69,226
  • 18
  • 123
  • 176
Sunny
  • 1,441
  • 2
  • 13
  • 22
  • What do you mean it runs fine, please post the output, maybe you only think it runs fine – AlexWien Jun 21 '13 at 12:32
  • And this is the deadlock! Where is the "has bowed back to me" message? – AlexWien Jun 21 '13 at 12:46
  • sorry, sometimes it gives Alphonse: Gaston has bowed to me! Gaston: Alphonse has bowed back to me! Gaston: Alphonse has bowed to me! Alphonse: Gaston has bowed back to me! sometimes Alphonse: Gaston has bowed to me! Gaston: Alphonse has bowed to me! – Sunny Jun 21 '13 at 12:53
  • @AlexWien Yes, you are right, sometimes its deadlock, sometimes its not – Sunny Jun 21 '13 at 12:55
  • possible duplicate of [Trying to wrap my wee brain around how threads deadlock](http://stackoverflow.com/questions/749641/trying-to-wrap-my-wee-brain-around-how-threads-deadlock) – thegrinner Mar 07 '14 at 13:47

5 Answers5

4

If you put a Thread.sleep(1000) after printing the first line and before making the call to bowBack, you should see a deadlock. This deadlock can happen anyway, it's will be rare.

You have two threads and two locks being acquired is different orders. This can leave each thread holding one lock but unable to get the second lock. i.e. a deadlock.

Note: threads take a lot of time to start which means the first thread can run to completion before the second one starts, so it is unlikely you will see the problem.


Here is a puzzler for you. This creates a deadlock, can you see why?

class A {
    static final int i;
    static {
        i = 128;

        Thread t = new Thread() {
            public void run() {
                System.out.println("i=" + i);
            }
        };
        t.start();
        try {
           t.join();
        } catch (InterruptedException e) {
           Thread.currentThread().interrupt();
        }
    }
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • i see no problem except this line Thread.currentThread().interrupt(); in catch block? but i can't get it – Sunny Jun 21 '13 at 13:03
  • someone can explain this problem? or i think i will have to post it as another question because now it has made me curious to know the answer? – Sunny Jun 21 '13 at 13:16
  • loading of classes and static blocks are implicitly `synchronized` This means you cannot access anything in a class in another thread while it is being initialised. In this case the initialisation is waiting for a thread which is using `A.i` i.e. it is waiting for the first thread to finish the static block. – Peter Lawrey Jun 21 '13 at 13:33
4

You have 2 objects, alphonse and gaston and 2 threads, Thread1 and Thread2

Suppose this happens:

  1. Thread1: alphonse enters the bow() method. and will hold a lock on the alphonse object

  2. Thread2: gaston enters the bow() method. and will hold a lock on the gaston object

  3. Thread1: alphonse while in the bow() method, calls bowBack() on the gaston object.

    -> Thread1 will block, since Thread2 already has the lock on gaston

  4. Thread2: gaston while in the bow() method, calls bowBack() on the alphonse object.

    -> Thread2 will block, since Thread1 already has the lock on alphonse

So now Thread1 is waiting for Thread2. And Thread2 is waiting for Thread1. This is a deadlock.

nos
  • 223,662
  • 58
  • 417
  • 506
3

As you are dealing with multithreading the operations in the two threads may happen in any order with respect to each other. So imagine both actors in this case execute bow and then they both try to execute bow_back. As bow and bow_back are synchronize both objects will be locked and you will not be able to perform bow_back on any of them. Both objects will wait until the other one is "free" and this will not happen as bow will not return before it "bows back".

Ivaylo Strandjev
  • 69,226
  • 18
  • 123
  • 176
1

The dealock will happen if both enters the bow() method at the same time, or during

System.out.println();

If you don't see both of the "has bowed back to me!" messages, then the deadlock occured!

If the first thread terminated before the second started there will be no deadlock.

Extend the code with Thread.sleep(1000);

public synchronized void bow(Friend bower) {
System.out.println(....);
Thread.sleep(1000);
...
}

then both threads enter bow() and dealock will occur.

AlexWien
  • 28,470
  • 6
  • 53
  • 83
0

in the end of bow A and G call bowBack, leading to a call of G.bow from A and a A.bow from G while bow of A and G is synchronized. So so they both wait for each other to finish.

user2504380
  • 535
  • 4
  • 12