How this java code produces deadlock?

元气小坏坏 提交于 2019-12-18 08:55:56

问题


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..


回答1:


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



回答2:


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.




回答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".




回答4:


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.




回答5:


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.



来源:https://stackoverflow.com/questions/17235212/how-this-java-code-produces-deadlock

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!