两个线程可以同时访问同步方法吗?

har*_*ish 12 java multithreading

    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();
    }
}
Run Code Online (Sandbox Code Playgroud)

当我运行这个程序时,我得到输出为

阿方斯:加斯顿向我鞠躬致敬!加斯顿:阿尔方斯向我鞠躬致敬!

那么两个线程可以同时访问同步方法吗?

Gra*_*ray 13

两个线程可以同时访问同步方法吗?

实例方法(如您的示例)在包含它们的对象上同步.在这种情况下,当您调用时,synchronized您将锁定该alphonse.bow(...)对象.alphonsegaston.bow(...).

有几种方法可以让对象的多个实例锁定在同一个对象上.

  • 你可以使方法成为gaston,static在这种情况下,他们将锁定类对象本身.每个类加载器只有一个这样的对象.

    public static synchronized void bow(Friend bower) {
    
    Run Code Online (Sandbox Code Playgroud)
  • 它们都可以锁定定义的静态对象.就像是:

    private static final Object lockObject = new Object();
    ...
    public void bow(Friend bower) {
        synchronized (lockObject) {
            ....
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 或者你可以传入对象来锁定,如果你不想让它静止.

您的输出可能如下所示:

  1. synchronized线程(可能)开始第一和电话gaston
  2. 这会锁定bow(alphonse)对象和输出:gaston
  3. 它叫Gaston: Alphonse has bowed to me!.
  4. 此调用锁定alphonse.bowBack(this)对象和输出:alphonse
  5. Alphonse: Gaston has bowed back to me!退出,解锁alphonse.bowBack(this)对象.
  6. alphonse退出,解锁gaston.bow(alphonse)对象.
  7. 然后gaston线程退出.
  8. gaston线程(可能)明年开始,并呼吁alphonse
  9. 这会锁定bow(gaston)对象和输出:alphonse
  10. 它叫Alphonse: Gaston has bowed to me!.
  11. 此调用锁定gaston.bowBack(this)对象和输出:gaston
  12. Gaston: Alphonse has bowed back to me!退出,解锁gaston.bowBack(this)对象.
  13. gaston退出,解锁alphonse.bow(gaston)对象.

这可能发生在许多不同的订单中.该alphonse线程可以先运行,即使它的alphonse方法被调用在以后的时间.锁定保存的唯​​一内容是调用start()if alphonse.bow(...)当前正在运行.正如@ user988052指出的那样,因为每个线程锁定自己的对象,然后尝试锁定另一个,所以很容易出现死锁.


NPE*_*NPE 10

那么两个线程可以同时访问同步方法吗?

是和否:

  • 是的,如果在类的不同实例上调用该方法.

  • 不,两个线程不能同时在类的同一个实例上调用synchronized方法.即使两个线程调用不同的方法(只要实例是相同的),情况也是如此.

  • 注意:如果synchronized方法在同一对象上调用另一个synchronized方法,则一个线程可以同时在同一对象上的两个同步方法中. (2认同)