简单的死锁示例

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了简单的死锁示例相关的知识,希望对你有一定的参考价值。

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

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

  1. 关联到一个有意义的“真实”编程场景
  2. 非常简短,简单直接

您有什么推荐的吗?

答案

也许是简单的银行情况。

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

}

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

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

另一答案

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

这是类比......

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

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

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

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

另一答案

一个更简单的死锁示例,有两个不同的资源和两个线程等待彼此释放资源。直接来自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();
  }
}
另一答案
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();
    }
}
另一答案

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

另一答案

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

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

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

另一答案

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

另一答案

来自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.ana

以上是关于简单的死锁示例的主要内容,如果未能解决你的问题,请参考以下文章

Java并发编程 - 一个简单的死锁示例和死锁的检查

死锁的简单示例

处理屏幕旋转上的片段重复(带有示例代码)

为啥这段代码会泄露? (简单的代码片段)

JavaSE8基础 死锁之同步嵌套 简单示例

在android中使用带有片段的roboguice的任何简单示例?