3

我正在尝试使用加入线程(JAVA)来创建死锁。根据我的理解,下面的程序应该终止。有人可以解释为什么下面的程序没有终止吗?

public class DeadLockUsingJoins2 {

    public static void main(String[] args) {

        AThread a = new AThread(null, "A");
        a.start();
        AThread b = new AThread(a, "B");
        b.start();
        a.t = b;
    }
}

class AThread extends Thread{

    public Thread t;

    public AThread(Thread thread, String name){
        super(name);
        this.t = thread;
    }

    @Override
    public void run(){
        try {
            if(t != null)
                t.join();
            else
            {
                Thread.sleep(5000);
            }
          //  if(t != null)
          //      t.join();
        } catch (InterruptedException e) {           
            e.printStackTrace();
            System.out.println("Somebody interruped thread - " + this.getName());
        }
        System.out.println("Winding Up thread - " + this.getName());
    }

}
4

5 回答 5

3

我看到没有终止的唯一原因是你的主线程到达了行

a.t = b;

在线程“a”到达行之前

if(t != null)
    t.join();

如果是这样,线程等待对方终止。

为了确保你得到一个死锁——你的类名暗示了这一点——你应该重新排序你的 main 方法:

public static void main(String[] args) {
    AThread a = new AThread(null, "A");
    AThread b = new AThread(a, "B");
    a.t = b;
    a.start();
    b.start();
}
于 2013-04-11T09:25:23.160 回答
2

在 at = b 之前添加一个暂停;

    b.start();
    Thread.sleep(100);
    a.t = b;

它会起作用的。但要可靠,它需要同步,例如这样

public class DeadLockUsingJoins2 {
    public static boolean go;

    public synchronized static void main(String[] args)
            throws InterruptedException {
        AThread a = new AThread(null, "A");
        AThread b = new AThread(a, "B");
        a.start();
        while (!go) {
            DeadLockUsingJoins2.class.wait();
        }
        a.t = b;
        b.start();
        DeadLockUsingJoins2.class.notifyAll();
    }
}

class AThread extends Thread {
    public Thread t;

    public AThread(Thread thread, String name) {
        super(name);
        this.t = thread;
    }

    @Override
    public void run() {
        try {
            if (t != null)
                t.join();
            else {
                synchronized (DeadLockUsingJoins2.class) {
                    DeadLockUsingJoins2.go = true;
                    DeadLockUsingJoins2.class.notifyAll();
                }
                Thread.sleep(5000);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Winding Up thread - " + this.getName());
    }
于 2013-04-11T09:26:32.543 回答
2

如果在实际调用任何创建的线程a.t = b;之前执行主线程,它将死锁。run()然后线程在join()调用上死锁。

编辑:为避免这种情况,您需要在主线程和您正在创建的线程之间使用某种同步。例如,发出使用开始的信号run()并在主线程中Object.notify()等待使用。Object.wait()

于 2013-04-11T09:23:04.493 回答
1

大多数时候它会终止。在 make 之后线程 B 开始运行(但未通过if(t != null)检查)时出现问题a.t = b

在这种情况下,由于内部原因,两个线程都在等待另一个线程完成join

于 2013-04-11T09:23:19.213 回答
1

所以你已经成功地写了一个死锁,因为你的每个线程都在等待另一个。

因为线程运行方法永远不会完成。

于 2013-04-11T09:23:16.313 回答