Contoh Deadlock Sederhana


92

Saya ingin menjelaskan jalan buntu threading untuk pemula. Saya telah melihat banyak contoh kebuntuan di masa lalu, beberapa menggunakan kode dan beberapa menggunakan ilustrasi (seperti 4 mobil terkenal ). Ada juga masalah klasik yang mudah menemui jalan buntu seperti The Dining Philosophers , tetapi ini mungkin terlalu rumit untuk dipahami sepenuhnya oleh seorang pemula.

Saya mencari contoh kode paling sederhana untuk menggambarkan apa itu kebuntuan. Contohnya harus:

  1. Berhubungan dengan skenario pemrograman "nyata" yang masuk akal
  2. Bersikaplah sangat singkat, sederhana, dan terus terang

Apa yang kamu sarankan?


mengapa tidak menggunakan 4 mobil terkenal, karena menurut saya cukup mudah.
kendaraan

2
Keempat mobil tersebut bukanlah skenario pemrograman, dan bukan hal yang sepele bagi seorang pemula untuk mengabstraksi masalah ke dalam bentuk 4 mobil. Saya menggunakannya, tetapi ingin menunjukkan skenario pemrograman di mana terjadi kebuntuan.
Roee Adler

Jawaban:


139

Mungkin situasi bank yang sederhana.

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

}

Jelas, jika ada dua utas yang mencoba menjalankan transfer ( a, b ) dan transfer ( b, a ) pada saat yang sama, maka kebuntuan akan terjadi karena mereka mencoba memperoleh sumber daya dalam urutan terbalik.

Kode ini juga bagus untuk mencari solusi kebuntuan juga. Semoga ini membantu!


1
Akan lebih baik jika Anda atau orang lain dapat memberikan solusi untuk masalah ini.
Jacky

2
@Jacky Solusi untuk masalah ini diposting oleh Will Hartung di sini: stackoverflow.com/questions/13326861/avoid-deadlock-example/…
Piotr Chojnacki

2
Saya bingung dengan sintaks Anda. Apa metode sync () itu? Saya akan mengerti jika sinkronisasi (dari); ... rilis (dari); diganti dengan sinkronisasi (dari) {...}
Ellen Spertus

1
@espertus syncbisa menjadi sesuatu seperti: sync(Account & a) { a.mutex.lock(); }.
vladon

1
javaworld.com/article/2075692/java-concurrency/… (Brian Goetz) menjelaskan solusi untuk masalah ini.
lingareddyk

59

Biarkan alam menjelaskan kebuntuan,

Kebuntuan: Katak vs. Ular

"Saya ingin sekali melihat mereka berpisah, tapi saya kelelahan," kata fotografer itu. "Katak itu sepanjang waktu mencoba menarik ular itu, tapi ular itu tidak mau melepaskannya" .

masukkan deskripsi gambar di sini


59
Lucu, tetapi tidak menjelaskan bagaimana kebuntuan terjadi dalam konteks pemrograman.
jalf

ok jalf, setidaknya Anda membenarkan downvote tersebut. Bagaimanapun, ini mirip dengan contoh "4 mobil". Sebuah lucu representasi bagaimana kebuntuan terlihat seperti.
Nick Dandoulakis

@Nick Dandoulakis: Presentasi bergambar yang sangat bagus. Gambar menjelaskan konsep kebuntuan
Rasmi Ranjan Nayak

@NickDandoulakis - Bukan contoh gambar yang bagus imho. Kode sederhana akan membantu di sini.
Erran Morad

13
Bagaimana ini bisa menjadi LUCU? Ular dan katak berbisa sedang memakan satu sama lain dan itu menakutkan !!!
vikkyhacks

53

Berikut adalah contoh kode dari departemen ilmu komputer sebuah universitas di Taiwan yang menunjukkan contoh java sederhana dengan penguncian sumber daya. Itu sangat relevan bagi saya "kehidupan nyata". Kode di bawah ini:

/**
 * 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
Masalahnya adalah ini bukanlah contoh "kehidupan nyata". Ini tentang "resource 1" dan "resource 2", dan alangkah baiknya jika benar-benar mengaitkannya dengan masalah pemrograman yang sebenarnya (maksud saya, secara langsung dapat digunakan dalam praktik, dengan mengacu pada domain masalah, dll.)
Jay

7
Contoh yang bagus menurut saya. Terima kasih.
James Raitsev

Kode ini tampaknya telah diterbitkan di beberapa buku yang berbeda ... stackoverflow.com/a/11338853/112705
Dan J

15

Jika metode1 () dan metode2 () keduanya akan dipanggil oleh dua atau banyak utas, ada kemungkinan besar terjadi kebuntuan karena jika utas 1 memperoleh kunci pada objek String saat menjalankan metode1 () dan utas 2 memperoleh kunci pada objek Integer saat menjalankan metode2 () keduanya akan menunggu satu sama lain untuk melepaskan kunci pada Integer dan String untuk melangkah lebih jauh, yang tidak akan pernah terjadi.

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

Cepat dan sederhana. Bagus.
pengguna1068352

13

Salah satu contoh kebuntuan sederhana yang saya temukan.

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

Saya suka contoh itu. Tetapi mengapa kelas SimpleDeadLock dikeluarkan dari Thread? Itu tidak perlu.
Charmin

1
Ini kurang lebih sama dengan jawaban ini: stackoverflow.com/a/1385868/1310566 . Dan apa yang private int indexdilakukannya di sana?
Simon Forsberg

6

Berikut contoh sederhana di 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();
}

5

Silakan lihat jawaban saya untuk pertanyaan ini . Intinya setiap kali dua utas perlu memperoleh dua sumber daya yang berbeda, dan melakukannya dalam urutan yang berbeda maka Anda bisa mendapatkan jalan buntu.


2
Saya tidak benar-benar mengerti gunanya menduplikasi informasi dari jawaban lain di sini. Saya berasumsi bahwa jika menurut Anda jawaban ini dapat ditingkatkan, Anda bebas mengeditnya sendiri.
djna

Saya pikir situasi ini disebut "mengunci inversi". Yah, saya tahu ini disebut locking inversion, karena saya menyebutnya begitu, tapi saya pikir itu juga istilah seni untuk itu :-)
Steve Jessop

4

Satu contoh yang dapat saya pikirkan adalah skenario Tabel, Senter, dan Baterai. Bayangkan sebuah senter dan sepasang baterai diletakkan di atas meja. Jika Anda berjalan ke meja ini dan mengambil baterai sementara orang lain memiliki senter, Anda berdua akan dipaksa untuk menatap satu sama lain dengan canggung sambil menunggu siapa yang akan meletakkan barang mereka kembali di atas meja. Ini adalah contoh kebuntuan. Anda dan orang tersebut sedang menunggu sumber daya tetapi tidak ada di antara Anda yang memberikan sumber daya mereka.

Demikian pula, dalam sebuah program, kebuntuan terjadi ketika dua atau lebih utas (Anda dan orang lain) menunggu dua atau lebih kunci (senter dan baterai) untuk dibebaskan dan keadaan dalam program sedemikian rupa sehingga kunci tersebut tidak pernah dibebaskan ( Anda berdua memiliki satu bagian dari teka-teki).

Jika Anda tahu java, beginilah cara Anda merepresentasikan masalah ini:

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

Jika Anda menjalankan contoh ini, Anda akan melihat bahwa terkadang segala sesuatunya berfungsi dengan baik dan benar. Tetapi terkadang program Anda tidak akan mencetak apa pun. Itu karena satu orang memiliki baterai sementara orang lain memiliki senter yang mencegah mereka menyalakan senter yang menyebabkan kebuntuan.

Contoh ini mirip dengan contoh yang diberikan oleh tutorial java: http://docs.oracle.com/javase/tutorial/essential/concurrency/deadlock.html

Contoh lainnya adalah contoh loop:

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

Contoh ini dapat mencetak 'Belum selesai' berulang kali atau tidak pernah dapat mencetak 'Belum selesai' sama sekali. Yang pertama terjadi karena utas pertama memperoleh kunci kelas dan tidak pernah melepaskannya yang mencegah 'stopLoop' diakses oleh utas kedua. Dan yang terbaru terjadi karena utas kedua dimulai sebelum utas pertama menyebabkan variabel 'selesai' menjadi benar sebelum utas pertama dijalankan.


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

3

Saya menganggap masalah Dining Philosophers sebagai salah satu contoh yang lebih sederhana dalam menunjukkan kebuntuan, karena 4 persyaratan kebuntuan dapat dengan mudah diilustrasikan oleh gambar (terutama menunggu melingkar).

Saya menganggap contoh dunia nyata jauh lebih membingungkan bagi pemula, meskipun saya tidak dapat memikirkan skenario dunia nyata yang baik di luar kepala saya sekarang (saya relatif tidak berpengalaman dengan konkurensi dunia nyata).


3

Baru-baru ini saya menyadari bahwa perkelahian antar pasangan tidak lain adalah kebuntuan .. dimana biasanya salah satu proses harus crash untuk menyelesaikannya, tentu saja itu prioritas yang lebih rendah (Boy;)).

Berikut analoginya ...

Proses1: Gadis (G) Proses2: Laki-laki (B) Sumber1: Maaf Sumber2
: Menerima kesalahan sendiri

Kondisi yang Diperlukan:
1. Saling Mengecualikan: Hanya satu dari G atau B yang dapat meminta maaf atau menerima Kesalahan sendiri pada satu waktu.
2. Tahan dan Tunggu: Pada suatu waktu, yang satu menahan Maaf dan yang lain Menerima kesalahan sendiri, yang satu menunggu Menerima kesalahan sendiri untuk melepaskan maaf, dan yang lain menunggu maaf melepaskan menerima kesalahannya sendiri.
3. Tidak ada preemption: Bahkan Tuhan tidak bisa memaksa B atau G untuk melepaskan Maaf atau Menerima kesalahan sendiri. Dan secara sukarela? Apakah kamu bercanda??
4. Penantian Melingkar: Sekali lagi, yang menahan maaf menunggu yang lain menerima kesalahannya sendiri, dan yang memegang menerima kesalahannya sendiri ingin yang lain meminta maaf terlebih dahulu. Jadi itu melingkar.

Jadi kebuntuan terjadi ketika semua kondisi ini berlaku pada saat yang sama, dan itu selalu terjadi dalam perkelahian pasangan;)

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


3

Satu lagi contoh kebuntuan sederhana dengan dua sumber daya berbeda dan dua utas menunggu satu sama lain untuk melepaskan sumber daya. Langsung dari example.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();
  }
}

If all goes as planned, deadlock will occur, and the program will never exit.Bisakah kita membuat contoh ini menjadi guaranteekebuntuan?
Erran Morad

Ini adalah kode yang sama seperti yang diposting Kyle , mengapa menambahkan jawaban ganda tiga tahun setelah jawaban lain? (dan mengapa saya mengomentarinya, tiga tahun kemudian?)
Simon Forsberg

2

Kebuntuan bisa terjadi dalam situasi ketika seorang Girl1ingin main mata Guy2, yang ditangkap oleh orang lain Girl2, dan Girl2ingin menggoda dengan Guy1yang tertangkap Girl1. Pasalnya, kedua gadis tersebut menunggu untuk saling dumping, kondisi tersebut dinamakan deadlock.

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

1

Masalah produsen-konsumen bersama dengan masalah para filsuf tempat makan mungkin sesederhana mungkin. Ini memiliki beberapa pseudocode yang mengilustrasikannya juga. Jika itu terlalu rumit untuk pemula, sebaiknya mereka berusaha lebih keras untuk memahaminya.


1

Pergi untuk skenario yang mungkin sederhana di mana kebuntuan dapat terjadi saat memperkenalkan konsep kepada siswa Anda. Ini akan melibatkan minimal dua utas dan minimal dua sumber daya (menurut saya). Tujuannya adalah untuk merekayasa skenario di mana utas pertama memiliki kunci pada sumber daya satu, dan menunggu kunci pada sumber daya dua dilepaskan, sementara pada saat yang sama utas dua memegang kunci pada sumber daya dua, dan sedang menunggu kunci sumber daya satu yang akan dirilis.

Tidak masalah apa sumber daya yang mendasarinya; demi kesederhanaan, Anda bisa menjadikannya sepasang file yang dapat ditulis oleh kedua utas.

EDIT: Ini mengasumsikan tidak ada komunikasi antar-proses selain kunci yang dipegang.


1

Agak sulit bagi saya untuk dipahami ketika membaca masalah para filsuf makan, IMHO kebuntuan sebenarnya terkait dengan alokasi sumber daya. Ingin berbagi contoh yang lebih sederhana di mana 2 Perawat harus berjuang untuk 3 peralatan untuk menyelesaikan tugas. Meskipun ditulis dalam bahasa java. Metode lock () sederhana dibuat untuk mensimulasikan bagaimana kebuntuan terjadi, sehingga dapat diterapkan dalam bahasa pemrograman lain juga. http://www.justexample.com/wp/example-of-deadlock/


1

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

}

Keluaran:

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 

Thread 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

Inilah satu kebuntuan sederhana di Jawa. Kami membutuhkan dua sumber daya untuk menunjukkan kebuntuan. Dalam contoh di bawah ini, satu sumber daya adalah kunci kelas (melalui metode sinkronisasi) dan yang lainnya adalah bilangan bulat '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();
    }
}

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
Bisakah Anda menambahkan beberapa teks untuk menjelaskan jawaban Anda.
Kmeixner

1

Inilah kebuntuan sederhana di 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;
        }
    }
}

Jika, suatu hari, Anda memanggil ini dari utas GUI, dan utas lain memanggilnya juga - Anda mungkin menemui jalan buntu. Utas lainnya masuk ke EndInvoke, menunggu utas GUI mengeksekusi delegasi sambil menahan kunci. Utas GUI memblokir kunci yang sama menunggu utas lain melepaskannya - yang tidak akan terjadi karena utas GUI tidak akan pernah tersedia untuk mengeksekusi delegasi yang ditunggu utas lain. (tentu saja, kunci di sini tidak sepenuhnya diperlukan - begitu pula EndInvoke, tetapi dalam skenario yang sedikit lebih kompleks, kunci dapat diperoleh oleh pemanggil karena alasan lain, yang mengakibatkan kebuntuan yang sama.)


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

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

Saya telah membuat Contoh DeadLock Kerja yang sangat Sederhana: -

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

Dalam contoh di atas, 2 utas sedang menjalankan metode tersinkronisasi dari dua objek berbeda. Metode tersinkronisasiA dipanggil oleh objek threadDeadLockA dan metode tersinkronisasiB dipanggil oleh objek threadDeadLockB. Di methodA referensi threadDeadLockB diteruskan dan di methodB referensi threadDeadLockA diteruskan. Sekarang setiap utas mencoba mengunci objek lain. Dalam methodA, thread yang menahan kunci pada threadDeadLockA mencoba untuk mengunci objek threadDeadLockB dan demikian pula di methodB, thread yang menahan kunci pada threadDeadLockB mencoba untuk mengunci threadDeadLockA. Jadi kedua utas akan menunggu selamanya menciptakan kebuntuan.


0

Izinkan saya menjelaskan lebih jelas menggunakan contoh yang memiliki lebih dari 2 utas.

Misalkan Anda memiliki n utas yang masing-masing memegang kunci L1, L2, ..., Ln. Sekarang katakanlah, mulai dari utas 1, setiap utas mencoba mendapatkan kunci utas tetangganya. Jadi, utas 1 diblokir karena mencoba mendapatkan L2 (karena L2 dimiliki oleh utas 2), utas 2 diblokir untuk L3 dan seterusnya. Utas n diblokir untuk L1. Ini sekarang menjadi kebuntuan karena tidak ada utas yang dapat dieksekusi.

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

Dalam contoh di atas, Anda dapat melihat bahwa ada tiga utas yang memegang Runnables task1, task2, dan task3. Sebelum pernyataan sleep(100), utas memperoleh kunci tiga objek kerja ketika mereka memasuki call()metode (karena adanya synchronized). Tapi begitu mereka mencoba ke callAnother()objek thread tetangga mereka, mereka diblokir, menyebabkan kebuntuan, karena kunci objek tersebut telah diambil.


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

0

Cara licik untuk menemui jalan buntu hanya dengan satu utas adalah mencoba mengunci mutex yang sama (non-rekursif) dua kali. Ini mungkin bukan contoh sederhana yang Anda cari, tetapi cukup yakin saya sudah menemukan kasus seperti itu.

#include <mutex>
#include <iostream>

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

0

Berikut adalah contoh detail saya untuk kebuntuan , setelah menghabiskan banyak waktu. Semoga membantu :)

package deadlock;

public class DeadlockApp {

    String s1 = "hello";
    String s2 = "world";

    Thread th1 = new Thread() {
        public void run() {
            System.out.println("Thread th1 has started");
            synchronized (s1) { //A lock is created internally (holds access of s1), lock will be released or unlocked for s1, only when it exits the block Line #23
                System.out.println("Executing first synchronized block of th1!");
                try {
                    Thread.sleep(1000);
                } catch(InterruptedException ex) {
                    System.out.println("Exception is caught in th1");
                }
                System.out.println("Waiting for the lock to be released from parrallel thread th1");
                synchronized (s2) { //As another has runned parallely Line #32, lock has been created for s2
                    System.out.println(s1 + s2);
                }

            }
            System.out.println("Thread th1 has executed");
        }
    };


    Thread th2 = new Thread() {
        public void run() {
            System.out.println("Thread th2 has started");
            synchronized (s2) { //A lock is created internally (holds access of s2), lock will be released or unlocked for s2, only when it exits the block Line #44
                System.out.println("Executing first synchronized block of th2!");
                try {
                    Thread.sleep(1000);
                } catch(InterruptedException ex) {
                    System.out.println("Exception is caught in th2");
                }
                System.out.println("Waiting for the lock to be released from parrallel thread th2");
                synchronized (s1) { //As another has runned parallely Line #11, lock has been created for s1
                    System.out.println(s1 + s2);
                }

            }
            System.out.println("Thread th2 has executed");
        }
    };

    public static void main(String[] args) {
        DeadlockApp deadLock = new DeadlockApp();
        deadLock.th1.start();
        deadLock.th2.start();
        //Line #51 and #52 runs parallely on executing the program, a lock is created inside synchronized method
        //A lock is nothing but, something like a blocker or wall, which holds access of the variable from being used by others.
        //Locked object is accessible, only when it is unlocked (i.e exiting  the synchronized block)
        //Lock cannot be created for primitive types (ex: int, float, double)
        //Dont forget to add thread.sleep(time) because if not added, then object access will not be at same time for both threads to create Deadlock (not actual runtime with lots of threads) 
        //This is a simple program, so we added sleep90 to create Deadlock, it will execute successfully, if it is removed. 
    }

    //Happy coding -- Parthasarathy S
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.