multithreading 简单的死锁示例

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1385843/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 01:03:58  来源:igfitidea点击:

Simple Deadlock Examples

multithreadinglanguage-agnosticdeadlock

提问by Roee Adler

I would like to explain threading deadlocks to newbies. I have seen many examples for deadlocks in the past, some using code and some using illustrations (like the famous 4 cars). There are also classic easily-deadlocked problems like The Dining Philosophers, but these may be too complex for a real newbie to fully grasp.

我想向新手解释线程死锁。以前看过很多死锁的例子,有的用代码,有的用插图(比如著名的4辆汽车)。还有像The Dining Philosophers这样经典容易死锁的问题,但这些问题对于真正的新手来说可能过于复杂而无法完全掌握。

I'm looking for the simplest code example to illustrate what deadlocks are. The example should:

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

  1. Relate to a "real" programming scenario that makes some sense
  2. Be very short, simple and straight forward
  1. 与有意义的“真实”编程场景相关
  2. 非常简短、简单和直接

What do you recommend?

你有什么建议吗?

回答by AAA

Maybe a simple bank situation.

也许是一个简单的银行情况。

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

}

Obviously, should there be two threads which attempt to run transfer(a, b) and transfer(b, a) at the same time, then a deadlock is going to occur because they try to acquire the resources in reverse order.

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

This code is also great for looking at solutions to the deadlock as well. Hope this helps!

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

回答by Nick Dandoulakis

Let nature explain deadlock,

让自然解释僵局,

Deadlock: Frog vs. Snake

僵局:青蛙对蛇

"I would love to have seen them go their separate ways, but I was exhausted," the photographer said. "The frog was all the time trying topull the snake off, but the snake justwouldn't let go".

“我很想看到他们分道扬镳,但我已经筋疲力尽了,”摄影师说。 “青蛙一直想把蛇拉下来,但蛇就是不放手”

enter image description here

在此处输入图片说明

回答by Kyle Rozendo

Here's a code example from the computer science department of a university in Taiwanshowing a simple java example with resource locking. That's very "real-life" relevant to me. Code below:

这是台湾某大学计算机科学系的代码示例,显示了一个带有资源锁定的简单 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();
  }
}

回答by Ashish Chaurasia

If method1() and method2() both will be called by two or many threads, there is a good chance of deadlock because if thread 1 acquires lock on String object while executing method1() and thread 2 acquires lock on Integer object while executing method2() both will be waiting for each other to release lock on Integer and String to proceed further, which will never happen.

如果method1()和method2()都会被两个或多个线程调用,那么死锁的可能性很大,因为如果线程1在执行method1()时获取String对象的锁,而线程2在执行method2时获取Integer对象的锁() 两者都将等待对方释放对 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");
        }
    }
}

回答by Hemanth

One of the simple deadlock example I have come across.

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

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

回答by Phillip Ngan

Here's a simple example in C++11.

这是 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();
}

回答by djna

Please see my answer to this question. Bottom line whenever two threads need to acquire two different resources, and do so in different orders then you can get deadlocks.

请看我对这个问题的回答。最重要的是,每当两个线程需要获取两种不同的资源,并且以不同的顺序执行时,就会出现死锁。

回答by Y_Y

One example I can think of is the Table, Flashlight, and Batteries scenario. Imagine a flashlight and a pair of batteries placed on top of a table. If you were to walk to this table and grab the batteries while another person has the flashlight you both will be forced to awkwardly stare at each other while waiting for who will first place their item back on the table. This is an example of deadlock. You and the person are waiting for resources but none of you are giving up their resource.

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

Similarly, in a program, deadlock occurs when two or more threads (you and the other person) are waiting for two or more locks (flashlight and batteries) to be freed and the circumstances in the program are such that the locks are never freed (you both have one piece of the puzzle).

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

If you know java, this is how you can represent this problem:

如果您了解 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();
    }
}

If you run this example you will notice that sometimes things work nice and correctly. But sometimes your program will just not print anything. That is because one person has the batteries while another person has the flashlight which prevents them from turning on the flashlight causing a deadlock.

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

This example is similar to the example given by the java tutorials: http://docs.oracle.com/javase/tutorial/essential/concurrency/deadlock.html

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

Another example is the loop example:

另一个例子是循环例子:

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

This example can either print 'Not done' over and over or it can never print 'Not done' at all. The first happens because the first thread acquires the class lock and never releases it preventing 'stopLoop' from being accessed by the second thread. And the latest happens because the second thread started before the first thread causing the 'done' variable to be true before the first thread executes.

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

回答by gstackoverflow

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

回答by i_am_saurabh

I recently realized that the fights between couples are nothing but a deadlock.. where usually one of the process has to crash to resolve it, of course it's the lesser priority one(Boy ;)).

我最近意识到夫妻之间的争吵只不过是一个僵局......通常一个进程必须崩溃才能解决它,当然它是次要的一个(男孩;))。

Here's the analogy...

这是类比...

Process1: Girl(G) Process2: Boy(B)
Resource1: Sorry Resource2: Accepting own mistake

Process1:Girl(G) Process2:Boy(B)
Resource1:抱歉 Resource2:接受自己的错误

Necessary Conditions:
1. Mutual Exclusion:Only one of G or B can say sorry or accept own Mistake at a time.
2. Hold and Wait:At a time, one is holding Sorry and other Accepting own mistake, one is waiting for Accepting own mistake to release sorry, and other is waiting for sorry to release accepting own mistake.
3. No preemption:Not even God can force B or G to release Sorry or Accepting own mistake. And voluntarily? Are you kidding me??
4. Circular Wait:Again, the one holding sorry waits for other to accept own mistakes, and one holding accept own mistakes want other to say sorry first. So it's circular.

必要条件:
1. 互斥:G 或 B 一次只能说抱歉或接受自己的错误。
2.hold and wait:一个时候,一个是抱着Sorry,另一个Accept自己的错误,一个是等Accept自己的错误释放sorry,另一个是等待sorry释放承认自己的错误。
3.不可抢占:即使是上帝也不能强迫B或G释放Sorry或Accepting自己的错误。而且是自愿的?你在跟我开玩笑吗??
4.循环等待:再次,抱对不起的人等着别人承认自己的错误,而抱着自己的错误的人要别人先说对不起。所以是圆形的。

So deadlocks occur when all these conditions are in effect at the same time, and that's always the case in a couple fight ;)

因此,当所有这些条件同时生效时,就会发生死锁,而在一对夫妇的战斗中总是如此;)

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

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