【问题标题】:Implementing deadlock condition实现死锁条件
【发布时间】:2013-10-20 13:10:43
【问题描述】:

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

【问题讨论】:

    标签: java multithreading


    【解决方案1】:

    这不是您陷入僵局的方式。实际上,这段代码看起来很安全 :-) 一次只有一个线程进入 sum/sub,因为您使用的是在“this”上同步的 synchronized。只有一个“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() 等等。

    【讨论】:

    • 对不起,我不明白。这可能是因为我是线程新手。根据我的理解,我只制作了一个线程示例类的对象。并且 Thread1 和 Thread2 正在竞争获取 sum() 和 sub() 上的锁。
    【解决方案2】:

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

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

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

    简单吗? =)

    【讨论】:

    • 您的示例不正确。只要Thread 不释放其锁,Thread2 就会被阻塞,但这不是死锁。当两个(或更多)线程被永久阻塞时,就会出现死锁情况,因为每个线程都被阻塞等待获取另一个拥有的独占资源。
    【解决方案3】:

    这是一个“行动中的死锁”的工作示例。基本上你需要做的(以及在现实世界中通常是如何发生的)是以相反的顺序锁定对象: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);
            }
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 2012-10-27
      • 2014-08-26
      • 1970-01-01
      • 2013-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多