Question About Deadlock Situation in Java

前端 未结 6 2264
鱼传尺愫
鱼传尺愫 2020-12-08 12:06

I\'m learning about deadlocks in Java, and there\'s this sample code from Sun\'s official tutorial:

Alphonse and Gaston are friends, and great belie

相关标签:
6条回答
  • 2020-12-08 12:30

    One important point to note is that it is not methods which are locked but object instances.

    When you call alphonse.bow(gaston), it tries to acquire the lock on alphonse. Once it has the lock, it prints a message, then calls gaston.bowBack(alphonse). At this point, it tries to acquire the lock on gaston. Once it has the lock, it prints a message, then releases the lock, and finally the lock on alphonse is released.

    In deadlock, the locks are acquired in such an order that there's no way for either thread to proceed.

    • Thread 1: acquires lock on alphonse
    • Thread 2: acquires lock on gaston
    • Thread 1: prints message
    • Thread 1: tries to acquire lock on gaston - can't, because Thread 2 already has it.
    • Thread 2: prints message
    • Thread 2: tries to acquire lock on alphonse - can't, because Thread 1 already has it.
    0 讨论(0)
  • 2020-12-08 12:31

    I'd have to double check, but I think a synchronized method locks on the class object, so it locks out other synchronized methods in the same class.

    I think it locks on the class object itself, so it even blocks different instances.

    Edit to add:

    Take a look at this part of the java language spec

    Each bow method grabs it's own objects monitor. Both then try to call the other object's bow back, and block waiting for the other monitor.

    0 讨论(0)
  • 2020-12-08 12:32

    alphonse and gaston are two different objects. Each object has an intrinsic monitor (lock) that is associated with it.

    It could happen like this:

    alphonse is created. His object monitor is 1.

    gaston is created. His object monitor is 2.

    alphonse.bow(gaston); alphonse now owns lock #1

    gaston.bow(alphonse); gaston now owns lock #2

    alphonse calls bowBack on gaston and is waiting for lock #2 gaston calls bowBack on alphonse and is waiting for lock #1

    Make sense? Using the synchronized keyword locks that instances monitor for the duration of the method. The example could be rewritten as follows:

    public class Deadlock {
        static class Friend {
            private final String name;
            public Friend(String name) {
                this.name = name;
            }
            public String getName() {
                return this.name;
            }
            public void bow(Friend bower) {
                synchronized(this) {            
                            System.out.format("%s: %s has bowed to me!%n", 
                        this.name, bower.getName());
                            bower.bowBack(this);
                }
            }
            public void bowBack(Friend bower) {
                synchronized(this) {
                            System.out.format("%s: %s has bowed back to me!%n",
                        this.name, bower.getName());
                }
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-08 12:37

    To add to simonn, et al.,

    If you would like to visualize this, compile and run the program and generate a thread dump of the running program. You can do this by typing a Ctrl-Break to a Windows console or issueing a kill -QUIT [pid] command to a *nix system. What this will provide you is a list of all of the Threads running in your system and where they are either running or waiting, as well as the monitors the threads are either locking on or waiting to lock on.

    If you change your Thread names in their constructors, you will have an easier time finding them in the full thread dump:

       new Thread(new Runnable() {
            public void run() { alphonse.bow(gaston); }
        }, "Alphonse").start();
        new Thread(new Runnable() {
            public void run() { gaston.bow(alphonse); }
        }, "Gaston").start();
    
    0 讨论(0)
  • 2020-12-08 12:48

    synchronized in a method definition is a shorthand for synchronizing on the object (this) itself. In essence this means that bow() and bowBack() cannot be invoked on the same Friend object mutually.

    Now if both Friends get into bow(), neither of them will be able to invoke each other's bowBack() method.

    0 讨论(0)
  • 2020-12-08 12:50

    Locks are held on Java objects, not java methods. So when synchronized is used on a method, it locks the "this" object. In the case of a static method, it locks the class object.

    You can explicitly specify the monitor object by using synchronized ( object ) { }

    0 讨论(0)
提交回复
热议问题