实现死锁条件

时间:2013-10-20 03:39:15

标签: java multithreading

我正在尝试实现死锁条件,但不知怎的,我无法让它工作。线程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();
        }
    }

3 个答案:

答案 0 :(得分:1)

这不是你如何陷入僵局。实际上这段代码似乎很安全:-)一次只有一个线程输入sum / sub,因为你使用的是synchronized,它在“this”上同步。只有一个“这个”,所以两个线程都试图获得相同的锁。

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

>

你能做的是:

a)在“threadexample”类中添加2个对象以锁定(按惯例,btw类应以大写字母开头):

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()等。

答案 1 :(得分:1)

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

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

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

    简单吗? =)

答案 2 :(得分:0)

这是“行动中的死锁”的一个有效例子。基本上你需要做的事情(以及现实世界中通常会发生的事情)是对象被锁定的顺序相反:一个线程中的第一个,第二个,第一个是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);
        }
    }

}