0

我正在尝试实现死锁条件,但不知何故我无法让它工作。线程 Thread1 和 Thread2 都进入了 run 函数,但只有一个进入 Sub/Sum 取决于谁先进入 run。示例:如果 Thread2 先进入运行,它将调用 sub(),而 Thread1 从不调用 sum()。我还添加了睡眠时间,以便 Thread2 在调用 sum() 之前睡眠,并且 Thread1 有足够的时间进入 Sum() 但 Thread1 永远不会进入。

    public class ExploringThreads {
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            threadexample a1 = new threadexample();
            Thread t1 = new Thread(a1, "Thread1");
            Thread t2 = new Thread(a1,"Thread2");
            t1.start();
            t2.start();
        }
    }
    class threadexample implements Runnable{
        public int a = 10;
        public void run(){
            if(Thread.currentThread().getName().equals("Thread1"))
                sum();
            else if(Thread.currentThread().getName().equals("Thread2"))
                sub();
        }

        public synchronized void sum()
        {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"In Sum");
            sub();
        }

        public synchronized void sub()
        {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"In Sub");
            sum();
        }
    }
4

3 回答 3

1

如果你真的想创建一个人工死锁,试试这个:
Thread1并且Thread2是两个想要访问同一个文件的线程。

  1. Thread1启动,要求锁定File1.docx并休眠 2 分钟。
  2. Thread2启动,并进行排他锁File2.docx,现在想要访问File1.docx.
  3. Thread1醒来,现在想要访问File2.docxThread2

现在,这是一个循环等待条件

简单的 ?=)

于 2013-10-20T03:47:36.547 回答
1

这不是你陷入僵局的方式。实际上,这段代码看起来很安全 :-) 一次只有一个线程进入 sum/sub,因为您使用的是同步的,它在“this”上同步。只有一个“this”,所以两个线程都试图获取相同的锁。

死锁发生,例如,当 Thread1 有一个锁,Thread2 有第二个锁,然后 Thread1 想获得 Thread2 的锁,同时仍然持有它的锁,而 Thread2 想获得 Thread1 的锁,同时仍然持有它的锁。

你可以做的是:

a) 在“threadexample”类中添加 2 个对象用于锁定(顺便说一句,类按惯例应以大写开头):

private final Object sumLock = new Object();
private final Object subLock = new Object();

b) 在两个 sum/sub 方法中删除“synchronized”关键字,而是在每个方法中使用 synchronized() {} 块。Sum 将被同​​步(sumLock){ /* sum 的主体在这里/ } 并且 sub 将被同步(subLock){ / sub 的主体在这里 */}。

在这种情况下,Thread1 将进入 sum(),获取 sumLock 并等待。Thread2 将进入 sub(),获取 subLock() 并等待。Thread1 会醒来,进入 sub() 并尝试获取 subLock,但它被 Thread2 持有,所以它一直等到 Thread2 释放它。在那个时候 Thread2 醒来,进入 sum() 并尝试获取由 Thread1 持有的 sumLock,因此 Thread2 等待 Thread1 释放它。

由于每个线程都在等待另一个线程,因此两个线程都不会前进 - 你有一个死锁。

@Edit:是的,您只有 1 个“threadexample”实例,并且 Thread1 和 Thread2 都在争夺锁,但是当其中一个获得锁时,它将在执行 sum/sub 或 sub/sum 后释放它。例如,假设 Thread1 是第一个并开始执行 sum()。它有锁。在这种情况下,Thread2 不会进入 sub(),因为它受到与 Thread1 相同的锁的保护。Thread1 将执行 sum(),然后是 sub(),然后它会释放锁——> Thread2 将进入 sub() 等。

于 2013-10-20T03:43:19.287 回答
0

这是“行动中的死锁”的一个工作示例。基本上你需要做的(以及在现实世界中通常是如何发生的)是以相反的顺序锁定对象:a first,b second in a thread and b first, a second in another:

package stackoverflow;

public class Deadlock {

    final static String a = new String("A");
    final static String b = new String("B");

    public static void main(String[] args) {

        final Thread abLock = new Thread() {
            @Override
            public void run() {
                lock(a, b);
            }
        };

        final Thread baLock = new Thread() {
            @Override
            public void run() {
                lock(b, a);
            }
        };

        abLock.start();
        baLock.start();

    }

    static void lock(String first, String second) {
        synchronized (first) {
            System.out.println(first);
            sleep();
            synchronized (second) {
                System.out.println(second);
            }
        }
    }

    static void sleep() {
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

}
于 2013-10-20T03:54:12.023 回答