如何在Java中同步工作

Dad*_*box 15 java multithreading deadlock

首先,这是一个示例:

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)

我没有得到的是阻塞是如何发生的.main函数启动两个线程,每个线程都开始自己的弓箭.

究竟什么'同步'阻止?为同一个对象运行相同的函数(我原来认为)?同一个类的所有对象的相同功能?同一对象的所有同步函数?同一类的所有对象的所有同步函数?

帮帮我吧

Edd*_*die 26

在Java中,每个都Object提供了线程对其进行synchronize或锁定的能力.方法同步时,该方法使用其对象实例作为锁.在您的示例中,方法bowbowBack都是synchronized,并且两者都在同一个类中Friend.这意味着执行这些方法的任何线程将在Friend实例上作为其锁定进行同步.

导致死锁的一系列事件是:

  1. 第一个线程调用开始alphonse.bow(gaston),这是synchronized在上alphonse Friend对象.这意味着Thread必须从该对象获取锁.
  2. 第二个线程开始通话gaston.bow(alphonse),这是synchronized在上gaston Friend对象.这意味着Thread必须从该对象获取锁.
  3. 第一个线程现在开始调用bowback并等待锁定gaston被释放.
  4. 第二个线程现在开始调用bowback并等待锁定alphonse被释放.

要更详细地显示事件序列:

  1. main()开始在主要的Therad中执行(称之为Thread#1),创建两个Friend实例.到现在为止还挺好.
  2. 主线程用代码启动它的第一个新线程(称之为线程#2)new Thread(new Runnable() { ....线程#2调用alphonse.bow(gaston),synchronizedalphonse Friend对象上.因此,线程#2获取alphonse对象的"锁定" 并进入该bow方法.
  3. 这里出现时间片,原始线程有机会进行更多处理.
  4. 主线程启动第二个新线程(称之为线程#3),就像第一个一样.线程#3调用gaston.bow(alphonse),在gaston Friend对象上同步.由于没有人获得gaston对象实例的"锁定",因此线程#3成功获取此锁并输入该bow方法.
  5. 这里出现时间片,而线程#2有机会进行更多处理.
  6. 线程#2现在调用bower.bowBack(this);,bower作为对实例的引用gaston.这是调用的逻辑等价物gaston.bowBack(alphonse).因此,这种方法就是synchronizedgaston实例上.此对象的锁已被获取并由另一个线程(线程#3)保持.因此,线程#2必须等待锁定gaston被释放.线程处于等待状态,允许线程#3进一步执行.
  7. 线程#3现在调用bowback,在这种情况下,它在逻辑上与调用相同alphonse.bowBack(gaston).为此,它需要获取alphonse实例的锁,但此锁由Thread#2保存.此线程现在处于等待状态.

而且你现在处于两个Thread都不能执行的位置.线程#2和线程#3都在等待锁定被释放.但是没有Thread可以在没有Thread进展的情况下释放锁.但是如果没有锁被释放,两个线程都无法取得进展.

因此:死锁!

死锁通常取决于发生的特定事件序列,这可能使得难以调试,因为它们很难再现.

  • 哦好的.所以锁属于整个对象.我不知道为什么我认为只是为被阻止的给定对象调用相同的同步方法.我猜这回答了我的问题. (2认同)