2009-09-06 79 views
79

Tôi muốn giải thích về việc deadlocks cho người mới. Tôi đã thấy nhiều ví dụ cho deadlocks trong quá khứ, một số sử dụng mã và một số bằng cách sử dụng hình ảnh minh họa (như 4 cars nổi tiếng). Ngoài ra còn có các vấn đề cổ điển dễ bế tắc như The Dining Philosophers, nhưng những điều này có thể quá phức tạp đối với một người mới thực sự nắm bắt đầy đủ.Ví dụ về Deadlock đơn giản

Tôi đang tìm ví dụ mã đơn giản nhất để minh họa những gì là khóa chết. Ví dụ nên:

  1. Liên quan đến một kịch bản chương trình "thực" mà làm cho một số cảm giác
  2. Hãy rất ngắn, đơn giản và thẳng về phía trước

gì bạn đề nghị?

+0

tại sao không sử dụng 4 xe hơi nổi tiếng, vì nó có vẻ khá đơn giản đối với tôi. – vehomzzz

+2

Bốn chiếc xe không phải là một kịch bản lập trình, và nó không tầm thường đối với một newbie để tóm tắt một vấn đề với hình thức của 4 chiếc xe. Tôi sử dụng chúng, nhưng muốn hiển thị một kịch bản lập trình mà bế tắc xảy ra. –

Trả lời

5

Vui lòng xem câu trả lời của tôi cho this question. Điểm mấu chốt bất cứ khi nào hai chủ đề cần để có được hai nguồn lực khác nhau, và làm như vậy trong các đơn đặt hàng khác nhau sau đó bạn có thể nhận được deadlocks.

+0

Bạn có thể dán mã có liên quan tại đây không? Cảm ơn. –

+2

Tôi không thực sự thấy điểm sao chép thông tin từ một câu trả lời khác ở đây. Tôi cho rằng nếu bạn nghĩ rằng câu trả lời này có thể được cải thiện, bạn sẽ tự do chỉnh sửa nó. – djna

+0

Tôi nghĩ tình trạng này được gọi là "khóa đảo ngược". Vâng, tôi biết nó được gọi là khóa đảo ngược, bởi vì tôi gọi nó là, nhưng tôi nghĩ đó cũng là thuật ngữ của nghệ thuật cho nó :-) –

1

producers-consumers problem cùng với các vấn đề về triết lý ăn uống có thể đơn giản như sắp xảy ra. Nó cũng có một số mã giả để minh họa nó. Nếu những thứ đó quá phức tạp đối với một người mới, họ nên cố gắng hơn để nắm bắt chúng.

46

Đây là ví dụ về mã từ the computer science department of a university in Taiwan hiển thị ví dụ đơn giản về java với khóa tài nguyên. Đó là "thực tế" có liên quan đến tôi. Mã bên dưới:

/** 
* 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(); 
    } 
} 
+1

Vấn đề là nó không thực sự là một ví dụ "thực tế". Đó là về "tài nguyên 1" và "tài nguyên 2", và nó sẽ là tốt đẹp để thực sự liên quan đến một vấn đề lập trình thực tế (tôi có nghĩa là, trực tiếp có thể sử dụng trong thực tế, với tham chiếu đến miền vấn đề vv) – Jay

+6

Ví dụ tốt theo ý kiến ​​của tôi. Cảm ơn. – JAM

+0

Mã này dường như đã được xuất bản trong một vài cuốn sách khác nhau ... http://stackoverflow.com/a/11338853/112705 –

125

Có thể là tình huống ngân hàng đơn giản.

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

} 

Rõ ràng, nếu như có hai luồng mà cố gắng chạy chuyển (a, b) và chuyển giao (b, a) cùng một lúc, sau đó một bế tắc sẽ xảy ra bởi vì họ cố gắng để có được các nguồn tài nguyên theo thứ tự ngược lại.

Mã này cũng rất tuyệt để xem các giải pháp cho bế tắc. Hi vọng điêu nay co ich!

+3

+1 rất gọn gàng, cảm ơn –

+1

Ví dụ thực sự tuyệt vời! – Jay

+0

ví dụ rất hay và đơn giản – Naveen

3

Tôi xem vấn đề Philosophers Dining là một trong những ví dụ đơn giản hơn khi hiển thị deadlocks, vì 4 yêu cầu bế tắc có thể dễ dàng được minh họa bằng bản vẽ (đặc biệt là vòng chờ).

Tôi coi các ví dụ thế giới thực sẽ khó hiểu hơn với những người mới, mặc dù tôi không thể nghĩ ra một kịch bản thế giới thực tốt trên đỉnh đầu ngay bây giờ (tôi khá thiếu kinh nghiệm với đồng thời trong thế giới thực) .

1

Dưới đây là một bế tắc đơn giản trong 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; 
     } 
    } 
} 

Nếu một ngày nào đó, bạn gọi này từ thread GUI, và thread khác gọi nó là tốt - bạn có thể bế tắc. Các chủ đề khác được để EndInvoke, chờ cho các chủ đề GUI để thực hiện các đại biểu trong khi giữ khóa. Các thread GUI chặn trên cùng một khóa chờ đợi cho thread khác để phát hành nó - mà nó sẽ không vì thread GUI sẽ không bao giờ có sẵn để thực hiện các đại biểu thread khác đang chờ đợi. (ofcourse khóa ở đây là không cần thiết nghiêm ngặt - cũng không phải là EndInvoke, nhưng trong một kịch bản hơi phức tạp hơn, một khóa có thể được mua bởi người gọi vì lý do khác, dẫn đến bế tắc tương tự.)

56

Hãy tính chất giải thích bế tắc,

Deadlock: Frog vs. Snake

"Tôi rất thích đã thấy họ đi cách riêng của họ, nhưng tôi đã kiệt sức," các nhiếp ảnh gia cho biết. "Chú ếch đã được tất cả các thời gian cố gắng để kéo con rắn ra, nhưng con rắn chỉ sẽ không buông tay".

enter image description here

+49

Dễ thương, nhưng không giải thích cách sự bế tắc xảy ra trong ngữ cảnh lập trình. – jalf

+0

ok jalf, ít nhất bạn đã biện minh cho downvote. Dù sao, nó tương tự như "4 chiếc xe" ví dụ. A * dễ thương * đại diện của một bế tắc như thế nào. –

+0

@Nick Dandoulakis: Trình bày ảnh tuyệt vời. Hình ảnh giải thích khái niệm bế tắc –

1

Go cho kịch bản simplist thể trong đó bế tắc có thể xảy ra khi introducting khái niệm cho sinh viên của mình. Điều này sẽ liên quan đến tối thiểu là hai chủ đề và tối thiểu là hai nguồn lực (tôi nghĩ). Mục đích là để thiết kế một kịch bản trong đó luồng đầu tiên có khóa trên tài nguyên, và đang đợi khóa trên tài nguyên hai được phát hành, trong khi cùng lúc đó hai luồng khóa trên tài nguyên hai và đang đợi khóa trên tài nguyên một được phát hành.

Không quan trọng những tài nguyên cơ bản là gì; vì lợi ích đơn giản, bạn chỉ có thể biến chúng thành một cặp tệp mà cả hai luồng đều có thể ghi.

CHỈNH SỬA: Điều này giả định không có liên lạc liên tiến trình nào ngoài các khóa được giữ.

3

Một ví dụ bế tắc đơn giản hơn với hai tài nguyên khác nhau và hai luồng đang chờ nhau giải phóng tài nguyên. Trực tiếp từ 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(); 
    } 
} 
+0

'Nếu tất cả diễn ra theo kế hoạch, bế tắc sẽ xảy ra, và chương trình sẽ không bao giờ thoát. 'Chúng ta có thể làm ví dụ này' đảm bảo 'bế tắc? –

+0

Đây là mã giống như [Kyle đã đăng] (http://stackoverflow.com/a/1385868/1310566), tại sao thêm câu trả lời trùng lặp ba năm sau câu trả lời khác? (và tại sao tôi bình luận về nó, ba năm sau?) –

1

tôi thấy rằng một chút khó hiểu khi đọc vấn đề các triết gia ăn uống, bế tắc IMHO là thực sự liên quan đến phân phối tài nguyên. Muốn chia sẻ một ví dụ đơn giản hơn khi 2 Y tá cần đấu tranh cho 3 thiết bị để hoàn thành một nhiệm vụ. Mặc dù nó được viết bằng java. Một phương thức lock() đơn giản được tạo ra để mô phỏng cách bế tắc xảy ra, vì vậy nó có thể áp dụng trong ngôn ngữ lập trình khác. http://www.justexample.com/wp/example-of-deadlock/

10

Nếu method1() và method2() cả hai sẽ được gọi bằng hai hoặc nhiều chủ đề, có một cơ hội tốt bế tắc vì nếu chuỗi 1 mua khóa trên đối tượng String trong khi thực hiện phương thức1() và thread 2 acquires lock trên đối tượng Integer trong khi thực hiện method2() cả hai sẽ chờ đợi nhau để giải phóng khóa trên Integer và String để tiếp tục, điều này sẽ không bao giờ xảy ra.

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

Ví dụ điển hình, mô tả rõ ràng khái niệm bế tắc. – Akash5288

+0

Nhanh chóng và đơn giản. Tốt đẹp. – user1068352

11

Một trong những ví dụ bế tắc đơn giản mà tôi đã gặp phải.

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

Tôi thích ví dụ đó. Nhưng tại sao lớp SimpleDeadLock lại xuất phát từ Thread? Đó là điều không cần thiết. – Charmin

+0

Điều này khá giống với câu trả lời này: http://stackoverflow.com/a/1385868/1310566. Và 'chỉ số int cá nhân' đó là gì? –

5

Tôi biết câu hỏi này đã được trả lời, nhưng đây là một ví dụ đơn giản: thời gian này sử dụng 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(); 
} 
2
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 
3

thời gian gần đây tôi nhận ra rằng chiến đấu giữa các cặp vợ chồng không có gì nhưng một bế tắc .. nơi thường một trong những quá trình đã sụp đổ để giải quyết nó, tất nhiên đó là ưu tiên ít hơn một (Boy;)).

Đây là sự tương tự ...

Process1: Girl (G) Process2: Boy (B)
Resource1: Xin lỗi Resource2: Chấp nhận sai lầm của riêng

Điều kiện cần thiết:
1 Loại trừ lẫn nhau: Chỉ một trong những G hoặc B có thể nói xin lỗi hoặc chấp nhận sai lầm riêng tại một thời điểm.
2. Giữ và chờ: Đồng thời, một đang giữ Xin lỗi và lỗi chấp nhận khác của chính mình, một đang chờ chấp nhận lỗi riêng để phát hành xin lỗi, và người khác đang chờ xin lỗi để phát hành chấp nhận sai lầm của chính mình.
3. Không được ưu tiên: Ngay cả Thượng đế cũng không thể buộc B hoặc G giải phóng Xin lỗi hoặc Chấp nhận sai lầm của chính mình. Và tự nguyện? Bạn đang đùa tôi à ??
4. Thông tư chờ đợi: Một lần nữa, người đang chờ xin lỗi chờ người khác chấp nhận sai lầm của chính mình, và một người đang chấp nhận những sai lầm của chính mình muốn người khác nói xin lỗi trước. Vì vậy, nó tròn.

Vì vậy, bế tắc xảy ra khi tất cả những điều kiện này có hiệu lực tại thời, và đó là luôn luôn như vậy trong một vài cuộc chiến;)

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

4

Một ví dụ tôi có thể nghĩ đến là Bảng , Đèn pin và Pin. Hãy tưởng tượng một đèn pin và một đôi pin được đặt trên một chiếc bàn. Nếu bạn đã đi bộ đến bàn này và lấy pin trong khi một người khác có đèn pin cả hai bạn sẽ bị buộc phải lúng túng nhìn chằm chằm vào nhau trong khi chờ đợi những người đầu tiên sẽ đặt mục của họ trở lại trên bàn. Đây là một ví dụ về bế tắc. Bạn và người đó đang chờ đợi tài nguyên nhưng không ai trong số bạn đang từ bỏ tài nguyên của họ.

Tương tự, trong một chương trình, bế tắc xảy ra khi hai hoặc nhiều chủ đề (bạn và người khác) chờ hai hoặc nhiều khóa (đèn pin và pin) được giải phóng và hoàn cảnh trong chương trình sao cho khóa không bao giờ được giải phóng (cả hai đều có một mảnh ghép).

Nếu bạn biết java, đây là cách bạn có thể đại diện cho vấn đề này:

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

Nếu bạn chạy ví dụ này, bạn sẽ nhận thấy rằng đôi khi mọi thứ làm việc tốt đẹp và chính xác. Nhưng đôi khi chương trình của bạn sẽ không in bất cứ thứ gì. Đó là bởi vì một người có pin trong khi một người khác có đèn pin ngăn họ bật đèn pin gây tắc nghẽn.

Ví dụ này cũng tương tự như ví dụ được đưa ra bởi các hướng dẫn java: http://docs.oracle.com/javase/tutorial/essential/concurrency/deadlock.html

Một ví dụ khác là ví dụ vòng lặp:

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

Ví dụ này có thể hoặc in 'Không thực hiện' lặp đi lặp hoặc nó không bao giờ có thể in 'Không hoàn thành'. Điều đầu tiên xảy ra bởi vì luồng đầu tiên có được khóa lớp và không bao giờ giải phóng nó ngăn chặn 'stopLoop' truy cập bởi luồng thứ hai. Và điều mới nhất xảy ra vì luồng thứ hai bắt đầu trước chuỗi đầu tiên khiến biến 'thực hiện' thành đúng trước khi chuỗi đầu tiên thực hiện.

1

Đây là một bế tắc đơn giản trong Java.Chúng tôi cần hai nguồn lực để chứng minh bế tắc. Trong ví dụ dưới đây, một tài nguyên là khóa lớp (thông qua phương pháp đồng bộ) và một trong những khác là một số nguyên 'i'

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

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

Tôi đã tạo ra một siêu đơn giản làm việc bế tắc Ví dụ: -

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

Trong ví dụ trên, 2 chủ đề đang thực hiện các phương thức được đồng bộ hóa của hai đối tượng khác nhau. Phương thức đồng bộ hóa được gọi bởi chuỗi đối tượngDeadLockA và phương thức đồng bộB được gọi bởi đối tượng threadDeadLockB. Trong methodA một tham chiếu của threadDeadLockB được truyền và trong phương thức methodB một tham chiếu của threadDeadLockA được truyền vào. Bây giờ mỗi chủ đề cố gắng để có được khóa trên đối tượng khác. Trong methodA thread đang nắm giữ một khóa trên threadDeadLockA đang cố gắng để có được khóa trên đối tượng threadDeadLockB và tương tự như trong methodB thread đang giữ một khóa trên threadDeadLockB đang cố gắng để có được khóa trên threadDeadLockA. Vì vậy, cả hai chủ đề sẽ chờ đợi mãi mãi tạo ra một bế tắc.

0

Để tôi giải thích rõ hơn bằng cách sử dụng ví dụ có nhiều hơn luồng.

Giả sử bạn có n chuỗi mỗi khóa giữ L1, L2, ..., Ln tương ứng. Bây giờ chúng ta hãy nói, bắt đầu từ thread 1, mỗi thread cố gắng để có được khóa của thread lân cận của nó. Vì vậy, thread 1 bị chặn vì cố gắng để có được L2 (như L2 là thuộc sở hữu của thread 2), thread 2 bị chặn cho L3 và như vậy. Chủ đề n bị chặn cho L1. Đây là một bế tắc vì không có luồng nào có thể thực hiện được.

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

Trong ví dụ trên, bạn có thể thấy rằng có ba luồng giữ Runnable s task1, task2 và task3. Trước tuyên bố sleep(100) các chủ đề có được khóa của ba đối tượng công việc khi họ nhập phương thức call() (do sự hiện diện của synchronized). Nhưng ngay sau khi họ cố gắng để callAnother() trên đối tượng của chủ đề hàng xóm của họ, họ bị chặn, dẫn đến một bế tắc, bởi vì những khóa của các đối tượng đã được thực hiện.

1

đơn giản ví dụ từ 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(); 
} 

} 

Output:

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 

Chủ đề Dump:

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 
1

Deadlock có thể xảy ra trong một tình huống khi một Girl1 đang muốn tán tỉnh với Guy2, bị bắt bởi một người khác Girl2Girl2 muốn tán tỉnh với một số Guy1 bị bắt bởi Girl1. Vì, cả hai cô gái đang chờ bán phá giá, tình trạng này được gọi là bế tắc.

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

vì vậy bạn đang nói ... 'không có khóa == orgy'?) – ycomp

+0

không, nó có thể có nghĩa là wedlock :) – supernova

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

Bạn có thể thêm một số văn bản để giải thích câu trả lời của bạn không. – Kmeixner

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

Một cách lén lút để bế tắc chỉ với một chủ đề duy nhất là cố gắng để khóa như nhau (không đệ quy) mutex hai lần. Đây có thể không phải là ví dụ đơn giản mà bạn đang tìm kiếm, nhưng chắc chắn tôi đã gặp phải những trường hợp như vậy rồi.

#include <mutex> 
#include <iostream> 

int main() 
{ 
    std::mutex m; 
    m.lock(); 
    m.lock(); 
    std::cout << "Expect never to get here because of a deadlock!"; 
} 
Các vấn đề liên quan