实现死锁条件



我正在尝试实现死锁条件,但不知何故我无法让它工作。线程 Thread1 和 Thread2 都在运行函数中输入,但只有一个线程进入 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();
        }
    }

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

  1. Thread1开始,要求锁定File1.docx并休眠 2 分钟。
  2. Thread2启动,并对File2.docx进行独占锁定,现在想要访问File1.docx
  3. Thread1醒来,现在想要访问由Thread2持有的File2.docx

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

简单 ? =)

这不是你陷入僵局的方式。实际上这段代码似乎很安全:-)一次只有一个线程输入 sum/sub,因为您正在使用在"this"上同步的同步。只有一个"this",因此两个线程都尝试获取相同的锁。

例如,当线程 1 有一个锁,线程 2 有第二个锁,然后线程 1 想要获取线程 2 的锁,同时仍然持有它的锁,线程

2 想要获取线程 1 的锁,同时仍然持有它的锁。

你可以做的是:

a) 添加 2 个对象以锁定 "threadexample" 类(顺便说一句,按照惯例,类应以大写开头):

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

b) 在两个 sum/sub 方法中删除 "syncd" 关键字,而是在每个方法中使用 syncd() {} 块。Sum 将被同步(sumLock) {/* sum's body go here/} and sub 将被同步(subLock) {/sub's body go here */}。

在这种情况下,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 后释放它。例如,假设线程 1 是第一个并开始执行 sum()。它有锁。在这种情况下,Thread2 不会进入 sub(),因为它受到与 Thread1 相同的锁的保护。Thread1 将执行 sum(),然后是 sub(),然后它将释放锁 --> Thread2 将进入 sub() 等。

这是"行动中的死锁"的一个工作示例。基本上你需要做的(以及这在现实世界中通常是如何发生的)是对象以相反的顺序被锁定:一个线程中的第一个,b第二个,另一个线程中的第二个:

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);
        }
    }
}