简单的死锁示例

时间:2009-09-06 14:54:31

标签: multithreading language-agnostic deadlock

我想向新手解释线程死锁。我见过许多死锁的例子,有些使用代码,有些使用插图(比如着名的4 cars)。还有像The Dining Philosophers这样经典的容易陷入僵局的问题,但这些问题可能过于复杂,无法让真正的新手完全掌握。

我正在寻找最简单的代码示例来说明死锁是什么。该示例应该:

  1. 与一个有意义的“真实”编程场景相关
  2. 非常简短,直截了当
  3. 你推荐什么?

28 个答案:

答案 0 :(得分:129)

可能是一个简单的银行情况。

class Account {
  double balance;

  void withdraw(double amount){
     balance -= amount;
  } 

  void deposit(double amount){
     balance += amount;
  } 

   void transfer(Account from, Account to, double amount){
        sync(from);
        sync(to);

        from.withdraw(amount);
        to.deposit(amount);

        release(to);
        release(from);
    }

}

显然,如果有两个线程试图同时运行传输( a,b )和传输( b,a ),那么死锁就是将要发生,因为他们试图以相反的顺序获取资源。

此代码也非常适合查看死锁的解决方案。希望这有帮助!

答案 1 :(得分:57)

让大自然解释死锁,

Deadlock: Frog vs. Snake

  

“我很想看到他们离开   他们各自的方式,但我是   疲惫不堪,“摄影师说。   “青蛙一直在努力   拉掉蛇,但蛇只是   不会放手“

enter image description here

答案 2 :(得分:52)

这是the computer science department of a university in Taiwan的代码示例,显示了一个带资源锁定的简单java示例。这与我的“现实生活”非常相关。代码如下:

/**
 * Adapted from The Java Tutorial
 * Second Edition by Campione, M. and
 * Walrath, K.Addison-Wesley 1998
 */

/**
 * This is a demonstration of how NOT to write multi-threaded programs.
 * It is a program that purposely causes deadlock between two threads that
 * are both trying to acquire locks for the same two resources.
 * To avoid this sort of deadlock when locking multiple resources, all threads
 * should always acquire their locks in the same order.
 **/
public class Deadlock {
  public static void main(String[] args){
    //These are the two resource objects 
    //we'll try to get locks for
    final Object resource1 = "resource1";
    final Object resource2 = "resource2";
    //Here's the first thread.
    //It tries to lock resource1 then resource2
    Thread t1 = new Thread() {
      public void run() {
        //Lock resource 1
        synchronized(resource1){
          System.out.println("Thread 1: locked resource 1");
          //Pause for a bit, simulating some file I/O or 
          //something. Basically, we just want to give the 
          //other thread a chance to run. Threads and deadlock
          //are asynchronous things, but we're trying to force 
          //deadlock to happen here...
          try{ 
            Thread.sleep(50); 
          } catch (InterruptedException e) {}

          //Now wait 'till we can get a lock on resource 2
          synchronized(resource2){
            System.out.println("Thread 1: locked resource 2");
          }
        }
      }
    };

    //Here's the second thread.  
    //It tries to lock resource2 then resource1
    Thread t2 = new Thread(){
      public void run(){
        //This thread locks resource 2 right away
        synchronized(resource2){
          System.out.println("Thread 2: locked resource 2");
          //Then it pauses, for the same reason as the first 
          //thread does
          try{
            Thread.sleep(50); 
          } catch (InterruptedException e){}

          //Then it tries to lock resource1.  
          //But wait!  Thread 1 locked resource1, and 
          //won't release it till it gets a lock on resource2.  
          //This thread holds the lock on resource2, and won't
          //release it till it gets resource1.  
          //We're at an impasse. Neither thread can run, 
          //and the program freezes up.
          synchronized(resource1){
            System.out.println("Thread 2: locked resource 1");
          }
        }
      }
    };

    //Start the two threads. 
    //If all goes as planned, deadlock will occur, 
    //and the program will never exit.
    t1.start(); 
    t2.start();
  }
}

答案 3 :(得分:14)

如果两个或多个线程都调用method1()和method2(),则很可能会出现死锁,因为如果线程1在执行method1()时获取String对象的锁定,并且线程2获取了对Integer对象的锁定在执行method2()时,两者都将等待彼此释放对Integer和String的锁定以继续进行,这将永远不会发生。

public void method1() {
    synchronized (String.class) {
        System.out.println("Acquired lock on String.class object");

        synchronized (Integer.class) {
            System.out.println("Acquired lock on Integer.class object");
        }
    }
}

public void method2() {
    synchronized (Integer.class) {
        System.out.println("Acquired lock on Integer.class object");

        synchronized (String.class) {
            System.out.println("Acquired lock on String.class object");
        }
    }
}

答案 4 :(得分:13)

我遇到的一个简单的死锁示例。

public class SimpleDeadLock {
   public static Object l1 = new Object();
   public static Object l2 = new Object();
   private int index;
   public static void main(String[] a) {
      Thread t1 = new Thread1();
      Thread t2 = new Thread2();
      t1.start();
      t2.start();
   }
   private static class Thread1 extends Thread {
      public void run() {
         synchronized (l1) {
            System.out.println("Thread 1: Holding lock 1...");
            try { Thread.sleep(10); }
            catch (InterruptedException e) {}
            System.out.println("Thread 1: Waiting for lock 2...");
            synchronized (l2) {
               System.out.println("Thread 2: Holding lock 1 & 2...");
            }
         }
      }
   }
   private static class Thread2 extends Thread {
      public void run() {
         synchronized (l2) {
            System.out.println("Thread 2: Holding lock 2...");
            try { Thread.sleep(10); }
            catch (InterruptedException e) {}
            System.out.println("Thread 2: Waiting for lock 1...");
            synchronized (l1) {
               System.out.println("Thread 2: Holding lock 2 & 1...");
            }
         }
      }
   }
}

答案 5 :(得分:6)

这是C ++ 11中的一个简单示例。

#include <mutex>    // mutex
#include <iostream> // cout 
#include <cstdio>   // getchar
#include <thread>   // this_thread, yield
#include <future>   // async
#include <chrono>   // seconds

using namespace std;
mutex _m1;
mutex _m2;

// Deadlock will occur because func12 and func21 acquires the two locks in reverse order

void func12()
{
    unique_lock<mutex> l1(_m1);
    this_thread::yield(); // hint to reschedule
    this_thread::sleep_for( chrono::seconds(1) );
    unique_lock<mutex> l2(_m2 );
}

void func21()
{
    unique_lock<mutex> l2(_m2);
    this_thread::yield(); // hint to reschedule
    this_thread::sleep_for( chrono::seconds(1) );
    unique_lock<mutex> l1(_m1);
}

int main( int argc, char* argv[] )
{
    async(func12);
    func21();
    cout << "All done!"; // this won't be executed because of deadlock
    getchar();
}

答案 6 :(得分:5)

请参阅我对this question的回答。只要两个线程需要获取两个不同的资源,并且以不同的顺序执行,那么你就可以获得死锁。

答案 7 :(得分:4)

我能想到的一个例子是桌子,手电筒和电池场景。想象一下手电筒和一对电池放在桌子上面。如果你走到这张桌子上拿着电池,而另一个人拿着手电筒,你会被迫尴尬地盯着对方,等待谁先将他们的物品放回桌子上。这是死锁的一个例子。你和这个人正在等待资源,但你们谁都没有放弃他们的资源。

类似地,在程序中,当两个或多个线程(您和另一个人)正在等待释放两个或更多个锁(手电筒和电池)并且程序中的情况使得锁是永远不会被释放(你们都有一块拼图)。

如果您了解java,则可以使用以下方法来表示此问题:

import java.util.concurrent.locks.*;

public class Deadlock1 {

    public static class Table {

        private static Lock Flashlight = new ReentrantLock();
        private static Lock Batteries = new ReentrantLock();        

        public static void giveFlashLightAndBatteries() {
            try {
                Flashlight.lock();
                Batteries.lock();
                System.out.println("Lights on");
            } finally {
                Batteries.unlock();
                Flashlight.unlock();
            }
        }

        public static void giveBatteriesAndFlashLight() {
            try {
                Batteries.lock();
                Flashlight.lock();
                System.out.println("Lights on");
            } finally {
                Flashlight.unlock();
                Batteries.unlock();
            }
        }
    }

    public static void main(String[] args) {
        // This thread represents person one
        new Thread(new Runnable() {
            public void run() { Table.giveFlashLightAndBatteries(); }
        }).start();

        // This thread represents person two
        new Thread(new Runnable() {
            public void run() { Table.giveBatteriesAndFlashLight(); }
        }).start();
    }
}

如果你运行这个例子,你会注意到有时事情很好而且正确。但有时你的程序不会打印任何东西。这是因为一个人有电池而另一个人有手电筒,这会阻止他们打开手电筒导致死锁。

此示例类似于java教程给出的示例:http://docs.oracle.com/javase/tutorial/essential/concurrency/deadlock.html

另一个例子是循环示例:

public class Deadlock2 {

    public static class Loop {
        private static boolean done = false;

        public static synchronized void startLoop() throws InterruptedException {
            while(!done) {
                Thread.sleep(1000);
                System.out.println("Not done");
            }
        }

        public static synchronized void stopLoop() {
            done = true;
        }

    }

    public static void main(String[] args) {
        // This thread starts the loop
        new Thread(new Runnable() {
            public void run() {
                try {
                    Loop.startLoop();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();

        // This thread stops the loop
        new Thread(new Runnable() {
            public void run() {
                Loop.stopLoop();
            }
        }).start();
    }
}

此示例可以反复打印“未完成”,或者根本不打印“未完成”。第一个发生是因为第一个线程获取了类锁并且从不释放它,防止第二个线程访问“stopLoop”。最新的情况发生是因为第二个线程在第一个线程之前启动,导致'done'变量在第一个线程执行之前为真。

答案 8 :(得分:3)

我认为Dining Philosophers问题是显示死锁的一个更简单的例子,因为4个死锁要求可以通过绘图(尤其是循环等待)轻松说明。

我认为现实世界的例子对新手来说更加困惑,虽然我现在无法想到一个好的现实世界场景(我对现实世界的并发性相对缺乏经验)。

答案 9 :(得分:3)

public class DeadLock {
    public static void main(String[] args) throws InterruptedException {
        Thread mainThread = Thread.currentThread();
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    mainThread.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        thread1.start();
        thread1.join();
    }
}

答案 10 :(得分:3)

另一个简单的死锁示例,包含两个不同的资源和两个等待彼此释放资源的线程。直接来自 examples.oreilly.com/jenut/Deadlock.java

 public class Deadlock {
  public static void main(String[] args) {
    // These are the two resource objects we'll try to get locks for
    final Object resource1 = "resource1";
    final Object resource2 = "resource2";
    // Here's the first thread.  It tries to lock resource1 then resource2
    Thread t1 = new Thread() {
      public void run() {
        // Lock resource 1
        synchronized(resource1) {
          System.out.println("Thread 1: locked resource 1");

          // Pause for a bit, simulating some file I/O or something.  
          // Basically, we just want to give the other thread a chance to
          // run.  Threads and deadlock are asynchronous things, but we're
          // trying to force deadlock to happen here...
          try { Thread.sleep(50); } catch (InterruptedException e) {}

          // Now wait 'till we can get a lock on resource 2
          synchronized(resource2) {
            System.out.println("Thread 1: locked resource 2");
          }
        }
      }
    };

    // Here's the second thread.  It tries to lock resource2 then resource1
    Thread t2 = new Thread() {
      public void run() {
        // This thread locks resource 2 right away
        synchronized(resource2) {
          System.out.println("Thread 2: locked resource 2");

          // Then it pauses, for the same reason as the first thread does
          try { Thread.sleep(50); } catch (InterruptedException e) {}

          // Then it tries to lock resource1.  But wait!  Thread 1 locked
          // resource1, and won't release it 'till it gets a lock on
          // resource2.  This thread holds the lock on resource2, and won't
          // release it 'till it gets resource1.  We're at an impasse. Neither
          // thread can run, and the program freezes up.
          synchronized(resource1) {
            System.out.println("Thread 2: locked resource 1");
          }
        }
      }
    };

    // Start the two threads. If all goes as planned, deadlock will occur, 
    // and the program will never exit.
    t1.start(); 
    t2.start();
  }
}

答案 11 :(得分:3)

我最近意识到情侣之间的争斗只不过是一个僵局......通常其中一个过程必须崩溃来解决它,当然这是次要的优先级(男孩;))。

这是类比......

过程1:女孩(G)过程2:男孩(B)
资源1:抱歉资源2:接受自己的错误

必要条件:
1。相互排斥: G或B中只有一个可以一次表示抱歉或接受自己的错误 的 2。等待:一次,一个抱着抱歉和其他接受自己的错误,一个正在等待接受自己的错误释放抱歉,其他等待抱歉释放接受自己的错误。
第3。没有先发制人:甚至上帝都不能强迫B或G释放抱歉或接受自己的错误。并自愿?你在跟我开玩笑吗? 的 4。循环等待:再次,持有抱歉的人等待其他人接受自己的错误,而一个持有接受自己错误的人则要先说对不起。所以它是循环的。

因此,当所有这些条件同时生效时会发生死锁,并且在一场战斗中总是如此;)

来源:http://www.quora.com/Saurabh-Pandey-3/Posts/Never-ending-couple-fights-a-deadlock

答案 12 :(得分:1)

producers-consumers problem和餐饮哲学家的问题可能就像它会得到的一样简单。它有一些伪代码也可以说明它。如果那些对于新手来说过于复杂,他们最好更加努力地抓住它们。

答案 13 :(得分:1)

public class DeadLock {

    public static void main(String[] args) {
        Object resource1 = new Object();
        Object resource2 = new Object();
        SharedObject s = new SharedObject(resource1, resource2);
        TestThread11 t1 = new TestThread11(s);
        TestThread22 t2 = new TestThread22(s);
        t1.start();
        t2.start();
    }

}

class SharedObject {
    Object o1, o2;
    SharedObject(Object o1, Object o2) {
        this.o1 = o1;
        this.o2 = o2;
    }
    void m1() {
        synchronized(o1) {
            System.out.println("locked on o1 from m1()");
            synchronized(o2) { 
                System.out.println("locked on o2 from m1()");
            }
        }
    }
    void m2() {
        synchronized(o2) {
            System.out.println("locked on o2 from m2()");
            synchronized(o1) { 
                System.out.println("locked on o1 from m2()");
            }
        }
    }
}

class TestThread11 extends Thread {
    SharedObject s;
    TestThread11(SharedObject s) {
        this.s = s;
    }
    public void run() {
        s.m1();
    }
}

class TestThread22 extends Thread {
    SharedObject s;
    TestThread22(SharedObject s) {
        this.s = s;
    }
    public void run() {
        s.m2();
    }
}

答案 14 :(得分:1)

Girl1想与Guy2调情时,可能会发生死锁,Girl2被另一个Girl2抓住,而Guy1想要调查被Girl1抓住的class OuchTheGirls { public static void main(String[] args) { final String resource1 = "Guy1"; final String resource2 = "Guy2"; // Girl1 tries to lock resource1 then resource2 Thread Girl1 = new Thread(() -> { synchronized (resource1) { System.out.println("Thread 1: locked Guy1"); try { Thread.sleep(100);} catch (Exception e) {} synchronized (resource2) { System.out.println("Thread 1: locked Guy2"); } } }); // Girl2 tries to lock Guy2 then Guy1 Thread Girl2 = new Thread(() -> { synchronized (resource2) { System.out.println("Thread 2: locked Guy2"); try { Thread.sleep(100);} catch (Exception e) {} synchronized (resource1) { System.out.println("Thread 2: locked Guy1"); } } }); Girl1.start(); Girl2.start(); } } 。因为,两个女孩都在等待相互倾倒,这种情况被称为死锁。

for (int i=0; i<9; i++){
        y += 50;
        x = 160;

        for (int j=0; j<9; j++){
            grid = [[UITextField alloc] initWithFrame:CGRectMake(x, y, 50 , 50)];
            grid.layer.borderWidth = 1;
            grid.textAlignment = NSTextAlignmentCenter;
            [[self view] addSubview:grid];

            x += 50;

            grid.text =  [@(j) stringValue];

            [initialArray addObject:grid];

        }

    }

答案 15 :(得分:1)

来自https://docs.oracle.com/javase/tutorial/essential/concurrency/deadlock.html

的简单示例
public class Deadlock {

public static void printMessage(String message) {

    System.out.println(String.format("%s %s ", Thread.currentThread().getName(), message));

}

private static class Friend {

    private String name;

    public Friend(String name) {
        this.name = name;
    }

    public void bow(Friend friend) {

        printMessage("Acquiring lock on " + this.name);

        synchronized(this) {
            printMessage("Acquired lock on " + this.name);
            printMessage(name + " bows " + friend.name);
            friend.bowBack(this);
        }

    }

    public void bowBack(Friend friend) {

        printMessage("Acquiring lock on " + this.name);

        synchronized (this) {
            printMessage("Acquired lock on " + this.name);
            printMessage(friend.name + " bows back");
        }

    }

}

public static void main(String[] args) throws InterruptedException {

    Friend one = new Friend("one");
    Friend two = new Friend("two");

    new Thread(new Runnable() {
        @Override
        public void run() {
            one.bow(two);
        }
    }).start();

    new Thread(new Runnable() {
        @Override
        public void run() {
            two.bow(one);
        }
    }).start();
}

}

输出:

Thread-0 Acquiring lock on one 
Thread-1 Acquiring lock on two 
Thread-0 Acquired lock on one 
Thread-1 Acquired lock on two 
Thread-1 two bows one 
Thread-0 one bows two 
Thread-1 Acquiring lock on one 
Thread-0 Acquiring lock on two 

线程转储:

2016-03-14 12:20:09
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.74-b02 mixed mode):

"DestroyJavaVM" #13 prio=5 os_prio=0 tid=0x00007f472400a000 nid=0x3783 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Thread-1" #12 prio=5 os_prio=0 tid=0x00007f472420d800 nid=0x37a3 waiting for monitor entry [0x00007f46e89a5000]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at com.anantha.algorithms.ThreadJoin$Friend.bowBack(ThreadJoin.java:102)
    - waiting to lock <0x000000076d0583a0> (a com.anantha.algorithms.ThreadJoin$Friend)
    at com.anantha.algorithms.ThreadJoin$Friend.bow(ThreadJoin.java:92)
    - locked <0x000000076d0583e0> (a com.anantha.algorithms.ThreadJoin$Friend)
    at com.anantha.algorithms.ThreadJoin$2.run(ThreadJoin.java:141)
    at java.lang.Thread.run(Thread.java:745)

"Thread-0" #11 prio=5 os_prio=0 tid=0x00007f472420b800 nid=0x37a2 waiting for monitor entry [0x00007f46e8aa6000]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at com.anantha.algorithms.ThreadJoin$Friend.bowBack(ThreadJoin.java:102)
    - waiting to lock <0x000000076d0583e0> (a com.anantha.algorithms.ThreadJoin$Friend)
    at com.anantha.algorithms.ThreadJoin$Friend.bow(ThreadJoin.java:92)
    - locked <0x000000076d0583a0> (a com.anantha.algorithms.ThreadJoin$Friend)
    at com.anantha.algorithms.ThreadJoin$1.run(ThreadJoin.java:134)
    at java.lang.Thread.run(Thread.java:745)

"Monitor Ctrl-Break" #10 daemon prio=5 os_prio=0 tid=0x00007f4724211000 nid=0x37a1 runnable [0x00007f46e8def000]
   java.lang.Thread.State: RUNNABLE
    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
    at java.net.SocketInputStream.read(SocketInputStream.java:170)
    at java.net.SocketInputStream.read(SocketInputStream.java:141)
    at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
    at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
    at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
    - locked <0x000000076d20afb8> (a java.io.InputStreamReader)
    at java.io.InputStreamReader.read(InputStreamReader.java:184)
    at java.io.BufferedReader.fill(BufferedReader.java:161)
    at java.io.BufferedReader.readLine(BufferedReader.java:324)
    - locked <0x000000076d20afb8> (a java.io.InputStreamReader)
    at java.io.BufferedReader.readLine(BufferedReader.java:389)
    at com.intellij.rt.execution.application.AppMain$1.run(AppMain.java:93)
    at java.lang.Thread.run(Thread.java:745)

"Service Thread" #9 daemon prio=9 os_prio=0 tid=0x00007f47240c9800 nid=0x3794 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C1 CompilerThread3" #8 daemon prio=9 os_prio=0 tid=0x00007f47240c6800 nid=0x3793 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread2" #7 daemon prio=9 os_prio=0 tid=0x00007f47240c4000 nid=0x3792 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread1" #6 daemon prio=9 os_prio=0 tid=0x00007f47240c2800 nid=0x3791 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread0" #5 daemon prio=9 os_prio=0 tid=0x00007f47240bf800 nid=0x3790 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Signal Dispatcher" #4 daemon prio=9 os_prio=0 tid=0x00007f47240be000 nid=0x378f waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00007f472408c000 nid=0x378e in Object.wait() [0x00007f46e98c5000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x000000076cf88ee0> (a java.lang.ref.ReferenceQueue$Lock)
    at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
    - locked <0x000000076cf88ee0> (a java.lang.ref.ReferenceQueue$Lock)
    at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
    at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)

"Reference Handler" #2 daemon prio=10 os_prio=0 tid=0x00007f4724087800 nid=0x378d in Object.wait() [0x00007f46e99c6000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x000000076cf86b50> (a java.lang.ref.Reference$Lock)
    at java.lang.Object.wait(Object.java:502)
    at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
    - locked <0x000000076cf86b50> (a java.lang.ref.Reference$Lock)
    at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)

"VM Thread" os_prio=0 tid=0x00007f4724080000 nid=0x378c runnable 

"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00007f472401f000 nid=0x3784 runnable 

"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00007f4724021000 nid=0x3785 runnable 

"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x00007f4724022800 nid=0x3786 runnable 

"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x00007f4724024800 nid=0x3787 runnable 

"GC task thread#4 (ParallelGC)" os_prio=0 tid=0x00007f4724026000 nid=0x3788 runnable 

"GC task thread#5 (ParallelGC)" os_prio=0 tid=0x00007f4724028000 nid=0x3789 runnable 

"GC task thread#6 (ParallelGC)" os_prio=0 tid=0x00007f4724029800 nid=0x378a runnable 

"GC task thread#7 (ParallelGC)" os_prio=0 tid=0x00007f472402b800 nid=0x378b runnable 

"VM Periodic Task Thread" os_prio=0 tid=0x00007f47240cc800 nid=0x3795 waiting on condition 

JNI global references: 16


Found one Java-level deadlock:
=============================
"Thread-1":
  waiting to lock monitor 0x00007f46dc003f08 (object 0x000000076d0583a0, a com.anantha.algorithms.ThreadJoin$Friend),
  which is held by "Thread-0"
"Thread-0":
  waiting to lock monitor 0x00007f46dc006008 (object 0x000000076d0583e0, a com.anantha.algorithms.ThreadJoin$Friend),
  which is held by "Thread-1"

Java stack information for the threads listed above:
===================================================
"Thread-1":
    at com.anantha.algorithms.ThreadJoin$Friend.bowBack(ThreadJoin.java:102)
    - waiting to lock <0x000000076d0583a0> (a com.anantha.algorithms.ThreadJoin$Friend)
    at com.anantha.algorithms.ThreadJoin$Friend.bow(ThreadJoin.java:92)
    - locked <0x000000076d0583e0> (a com.anantha.algorithms.ThreadJoin$Friend)
    at com.anantha.algorithms.ThreadJoin$2.run(ThreadJoin.java:141)
    at java.lang.Thread.run(Thread.java:745)
"Thread-0":
    at com.anantha.algorithms.ThreadJoin$Friend.bowBack(ThreadJoin.java:102)
    - waiting to lock <0x000000076d0583e0> (a com.anantha.algorithms.ThreadJoin$Friend)
    at com.anantha.algorithms.ThreadJoin$Friend.bow(ThreadJoin.java:92)
    - locked <0x000000076d0583a0> (a com.anantha.algorithms.ThreadJoin$Friend)
    at com.anantha.algorithms.ThreadJoin$1.run(ThreadJoin.java:134)
    at java.lang.Thread.run(Thread.java:745)

Found 1 deadlock.

Heap
 PSYoungGen      total 74752K, used 9032K [0x000000076cf80000, 0x0000000772280000, 0x00000007c0000000)
  eden space 64512K, 14% used [0x000000076cf80000,0x000000076d8520e8,0x0000000770e80000)
  from space 10240K, 0% used [0x0000000771880000,0x0000000771880000,0x0000000772280000)
  to   space 10240K, 0% used [0x0000000770e80000,0x0000000770e80000,0x0000000771880000)
 ParOldGen       total 171008K, used 0K [0x00000006c6e00000, 0x00000006d1500000, 0x000000076cf80000)
  object space 171008K, 0% used [0x00000006c6e00000,0x00000006c6e00000,0x00000006d1500000)
 Metaspace       used 3183K, capacity 4500K, committed 4864K, reserved 1056768K
  class space    used 352K, capacity 388K, committed 512K, reserved 1048576K

答案 16 :(得分:1)

这是Java中的一个简单死锁。我们需要两个资源来演示死锁。在下面的示例中,一个资源是类锁(通过同步方法),另一个是整数&#39; i&#39;

public class DeadLock {

    static int i;
    static int k;

    public static synchronized void m1(){
        System.out.println(Thread.currentThread().getName()+" executing m1. Value of i="+i);

        if(k>0){i++;}

        while(i==0){
            System.out.println(Thread.currentThread().getName()+" waiting in m1 for i to be > 0. Value of i="+i);
            try { Thread.sleep(10000);} catch (InterruptedException e) { e.printStackTrace(); }
        }
    }

    public static void main(String[] args) {

        Thread t1 = new Thread("t1") {
            public void run() {
                m1();
            }
        };

        Thread t2 = new Thread("t2") {
            public void run() {
                try { Thread.sleep(100);} catch (InterruptedException e) { e.printStackTrace(); }
                k++;
                m1();
            }
        };

        t1.start();
        t2.start();
    }
}

答案 17 :(得分:1)

我在阅读餐饮哲学家的问题时发现有点难以理解,僵局IMHO实际上与资源分配有关。 想分享一个更简单的例子,其中2护士需要争取3个装备才能完成任务。 虽然它是用java编写的。创建一个简单的lock()方法来模拟死锁的发生方式,因此它也可以应用于其他编程语言。 http://www.justexample.com/wp/example-of-deadlock/

答案 18 :(得分:1)

选择简单的可能场景,在向学生介绍概念时可能会发生死锁。这将涉及至少两个线程和至少两个资源(我认为)。目标是设计一个场景,其中第一个线程锁定资源1,并等待资源2的锁定被释放,同时线程2持有对资源2的锁定,并且正在等待锁定资源一将被释放。

底层资源是什么并不重要;为了简单起见,你可以让它们成为两个线程都能写入的文件对。

编辑:假设除了持有的锁之外没有进程间通信。

答案 19 :(得分:1)

这是C#中的一个简单死锁。

void UpdateLabel(string text) {
   lock(this) {
      if(MyLabel.InvokeNeeded) {
        IAsyncResult res =  MyLable.BeginInvoke(delegate() {
             MyLable.Text = text;
            });
         MyLabel.EndInvoke(res);
        } else {
             MyLable.Text = text;
        }
    }
}

如果有一天,你从GUI线程调用它,而另一个线程也调用它 - 你可能会死锁。另一个线程转到EndInvoke,等待GUI线程执行 在拿着锁的同时委托。 GUI线程在同一个锁上阻塞,等待另一个线程释放它 - 它不会因为GUI线程永远不可用于执行另一个线程正在等待的委托。 (当然,这里的锁并不是严格需要的 - 也许也不是EndInvoke,但是在稍微复杂的情况下,调用者可能会因其他原因获取锁定,导致同样的死锁。)

答案 20 :(得分:0)

public class DeadlockProg {

    /**
     * @Gowtham Chitimi Reddy IIT(BHU);
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        final Object ob1 = new Object();
        final Object ob2 = new Object();
        Thread t1 = new Thread(){
            public void run(){
                synchronized(ob1){
                    try{
                        Thread.sleep(100);
                    }
                    catch(InterruptedException e){
                        System.out.println("Error catched");
                    }
                    synchronized(ob2){

                    }
                }

            }
        };
        Thread t2 = new Thread(){
            public void run(){
                synchronized(ob2){
                    try{
                        Thread.sleep(100);
                    }
                    catch(InterruptedException e){
                        System.out.println("Error catched");
                    }
                    synchronized(ob1){                      
                    }
                }               
            }
        };
        t1.start();
        t2.start();
    }

}

答案 21 :(得分:0)

package ForkBlur;

public class DeadLockTest {
  public static void main(String args[]) {

    final DeadLockTest t1 = new DeadLockTest();
    final DeadLockTest t2 = new DeadLockTest();

    Runnable r1 = new Runnable() {

        @Override
        public void run() {
            try {

                synchronized (t1) {
                    System.out
                            .println("r1 has locked t1, now going to sleep");
                    Thread.sleep(100);
                    System.out
                            .println("r1 has awake , now going to aquire lock for t2");
                    synchronized (t2) {
                        Thread.sleep(100);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    };

    Runnable r2 = new Runnable() {

        @Override
        public void run() {
            try {

                synchronized (t2) {
                    System.out
                            .println("r2 has aquire the lock of t2 now going to sleep");
                    Thread.sleep(100);
                    System.out
                            .println("r2 is awake , now going to aquire the lock from t1");
                    synchronized (t1) {
                        Thread.sleep(100);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    };

    new Thread(r1).start();
    new Thread(r2).start();
  }
}

答案 22 :(得分:0)

我创建了一个超简单工作死锁示例: -

package com.thread.deadlock;

public class ThreadDeadLockClient {

    public static void main(String[] args) {
        ThreadDeadLockObject1 threadDeadLockA = new ThreadDeadLockObject1("threadDeadLockA");
        ThreadDeadLockObject2 threadDeadLockB = new ThreadDeadLockObject2("threadDeadLockB");

        new Thread(new Runnable() {

            @Override
            public void run() {
                threadDeadLockA.methodA(threadDeadLockB);

            }
        }).start();

        new Thread(new Runnable() {

            @Override
            public void run() {
                threadDeadLockB.methodB(threadDeadLockA);

            }
        }).start();
    }
}

package com.thread.deadlock;

public class ThreadDeadLockObject1 {

    private String name;

    ThreadDeadLockObject1(String name){
        this.name = name;
    }

    public  synchronized void methodA(ThreadDeadLockObject2 threadDeadLockObject2) {
        System.out.println("In MethodA "+" Current Object--> "+this.getName()+" Object passed as parameter--> "+threadDeadLockObject2.getName());
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        threadDeadLockObject2.methodB(this);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }   
}

package com.thread.deadlock;

public class ThreadDeadLockObject2 {

    private String name;

    ThreadDeadLockObject2(String name){
        this.name = name;
    }

    public  synchronized void methodB(ThreadDeadLockObject1 threadDeadLockObject1) {
        System.out.println("In MethodB "+" Current Object--> "+this.getName()+" Object passed as parameter--> "+threadDeadLockObject1.getName());
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        threadDeadLockObject1.methodA(this);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

在上面的示例中,2个线程正在执行两个不同对象的同步方法。 同步方法A由对象threadDeadLockA调用,同步方法B由对象threadDeadLockB调用。在methodA中传递threadDeadLockB的引用,并在方法B中传递threadDeadLockA的引用。现在每个线程都试图锁定另一个对象。在methodA中,对threadDeadLockA持有锁的线程正在尝试锁定对象threadDeadLockB,类似地,在methodB中,对threadDeadLockB持有锁的线程正在尝试锁定threadDeadLockA。因此,两个线程将永远等待造成死锁。

答案 23 :(得分:0)

让我使用超过 2 个线程的示例更清楚地解释一下。

让我们假设您有n个线程,每个线程分别持有锁L1,L2,...,Ln。现在让我们说,从线程1开始,每个线程都试图获取其邻居线程的锁。因此,线程1被阻止以尝试获取L2(因为L2由线程2拥有),线程2被阻塞用于L3,依此类推。线程n被阻塞为L1。现在这是一个死锁,因为没有线程能够执行。

html

在上面的示例中,您可以看到有三个线程持有class ImportantWork{ synchronized void callAnother(){ } synchronized void call(ImportantWork work) throws InterruptedException{ Thread.sleep(100); work.callAnother(); } } class Task implements Runnable{ ImportantWork myWork, otherWork; public void run(){ try { myWork.call(otherWork); } catch (InterruptedException e) { } } } class DeadlockTest{ public static void main(String args[]){ ImportantWork work1=new ImportantWork(); ImportantWork work2=new ImportantWork(); ImportantWork work3=new ImportantWork(); Task task1=new Task(); task1.myWork=work1; task1.otherWork=work2; Task task2=new Task(); task2.myWork=work2; task2.otherWork=work3; Task task3=new Task(); task3.myWork=work3; task3.otherWork=work1; new Thread(task1).start(); new Thread(task2).start(); new Thread(task3).start(); } } 的task1,task2和task3。在语句Runnable之前,线程在进入sleep(100)方法时获取三个工作对象的锁(由于存在call())。但是一旦他们在邻居线程的对象上尝试synchronized,它们就会被阻塞,从而导致死锁,因为这些对象的锁已经被锁定了。

答案 24 :(得分:0)

package test.concurrent;
public class DeadLockTest {
   private static long sleepMillis;
   private final Object lock1 = new Object();
   private final Object lock2 = new Object();

   public static void main(String[] args) {
       sleepMillis = Long.parseLong(args[0]);
       DeadLockTest test = new DeadLockTest();
       test.doTest();
   }

   private void doTest() {
       Thread t1 = new Thread(new Runnable() {
           public void run() {
               lock12();
           }
       });
       Thread t2 = new Thread(new Runnable() {
           public void run() {
               lock21();
           }
       });
       t1.start();
       t2.start();
   }

   private void lock12() {
       synchronized (lock1) {
           sleep();
           synchronized (lock2) {
               sleep();
           }
       }
   }

   private void lock21() {
       synchronized (lock2) {
           sleep();
           synchronized (lock1) {
               sleep();
           }
       }
   }

   private void sleep() {
       try {
           Thread.sleep(sleepMillis);
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
   }
}
To run the deadlock test with sleep time 1 millisecond:
java -cp . test.concurrent.DeadLockTest 1

答案 25 :(得分:0)

CountDownLatch countDownLatch = new CountDownLatch(1);
ExecutorService executorService = ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.execute(() -> {
    Future<?> future = executorService.submit(() -> {
        System.out.println("generated task");
    });
    countDownLatch.countDown();
    try {
        future.get();
    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (ExecutionException e) {
         e.printStackTrace();
    }
});


countDownLatch.await();
executorService.shutdown();

答案 26 :(得分:0)

只用一个线程来实现死锁的偷偷摸摸的方法是尝试两次锁定相同的(非递归)互斥锁。这可能不是您正在寻找的简单示例,但我确实已经遇到过这种情况。

#include <mutex>
#include <iostream>

int main()
{
  std::mutex m;
  m.lock();
  m.lock();
  std::cout << "Expect never to get here because of a deadlock!";
}

答案 27 :(得分:0)

这是我花费大量时间后死锁的详细示例。希望对您有所帮助:)

char name[20]