我想向新手解释线程死锁。我见过许多死锁的例子,有些使用代码,有些使用插图(比如着名的4 cars)。还有像The Dining Philosophers这样经典的容易陷入僵局的问题,但这些问题可能过于复杂,无法让真正的新手完全掌握。
我正在寻找最简单的代码示例来说明死锁是什么。该示例应该:
你推荐什么?
答案 0 :(得分:129)
可能是一个简单的银行情况。
class Account {
double balance;
void withdraw(double amount){
balance -= amount;
}
void deposit(double amount){
balance += amount;
}
void transfer(Account from, Account to, double amount){
sync(from);
sync(to);
from.withdraw(amount);
to.deposit(amount);
release(to);
release(from);
}
}
显然,如果有两个线程试图同时运行传输( a,b )和传输( b,a ),那么死锁就是将要发生,因为他们试图以相反的顺序获取资源。
此代码也非常适合查看死锁的解决方案。希望这有帮助!
答案 1 :(得分:57)
答案 2 :(得分:52)
这是the computer science department of a university in Taiwan的代码示例,显示了一个带资源锁定的简单java示例。这与我的“现实生活”非常相关。代码如下:
/**
* Adapted from The Java Tutorial
* Second Edition by Campione, M. and
* Walrath, K.Addison-Wesley 1998
*/
/**
* This is a demonstration of how NOT to write multi-threaded programs.
* It is a program that purposely causes deadlock between two threads that
* are both trying to acquire locks for the same two resources.
* To avoid this sort of deadlock when locking multiple resources, all threads
* should always acquire their locks in the same order.
**/
public class Deadlock {
public static void main(String[] args){
//These are the two resource objects
//we'll try to get locks for
final Object resource1 = "resource1";
final Object resource2 = "resource2";
//Here's the first thread.
//It tries to lock resource1 then resource2
Thread t1 = new Thread() {
public void run() {
//Lock resource 1
synchronized(resource1){
System.out.println("Thread 1: locked resource 1");
//Pause for a bit, simulating some file I/O or
//something. Basically, we just want to give the
//other thread a chance to run. Threads and deadlock
//are asynchronous things, but we're trying to force
//deadlock to happen here...
try{
Thread.sleep(50);
} catch (InterruptedException e) {}
//Now wait 'till we can get a lock on resource 2
synchronized(resource2){
System.out.println("Thread 1: locked resource 2");
}
}
}
};
//Here's the second thread.
//It tries to lock resource2 then resource1
Thread t2 = new Thread(){
public void run(){
//This thread locks resource 2 right away
synchronized(resource2){
System.out.println("Thread 2: locked resource 2");
//Then it pauses, for the same reason as the first
//thread does
try{
Thread.sleep(50);
} catch (InterruptedException e){}
//Then it tries to lock resource1.
//But wait! Thread 1 locked resource1, and
//won't release it till it gets a lock on resource2.
//This thread holds the lock on resource2, and won't
//release it till it gets resource1.
//We're at an impasse. Neither thread can run,
//and the program freezes up.
synchronized(resource1){
System.out.println("Thread 2: locked resource 1");
}
}
}
};
//Start the two threads.
//If all goes as planned, deadlock will occur,
//and the program will never exit.
t1.start();
t2.start();
}
}
答案 3 :(得分:14)
如果两个或多个线程都调用method1()和method2(),则很可能会出现死锁,因为如果线程1在执行method1()时获取String对象的锁定,并且线程2获取了对Integer对象的锁定在执行method2()时,两者都将等待彼此释放对Integer和String的锁定以继续进行,这将永远不会发生。
public void method1() {
synchronized (String.class) {
System.out.println("Acquired lock on String.class object");
synchronized (Integer.class) {
System.out.println("Acquired lock on Integer.class object");
}
}
}
public void method2() {
synchronized (Integer.class) {
System.out.println("Acquired lock on Integer.class object");
synchronized (String.class) {
System.out.println("Acquired lock on String.class object");
}
}
}
答案 4 :(得分:13)
我遇到的一个简单的死锁示例。
public class SimpleDeadLock {
public static Object l1 = new Object();
public static Object l2 = new Object();
private int index;
public static void main(String[] a) {
Thread t1 = new Thread1();
Thread t2 = new Thread2();
t1.start();
t2.start();
}
private static class Thread1 extends Thread {
public void run() {
synchronized (l1) {
System.out.println("Thread 1: Holding lock 1...");
try { Thread.sleep(10); }
catch (InterruptedException e) {}
System.out.println("Thread 1: Waiting for lock 2...");
synchronized (l2) {
System.out.println("Thread 2: Holding lock 1 & 2...");
}
}
}
}
private static class Thread2 extends Thread {
public void run() {
synchronized (l2) {
System.out.println("Thread 2: Holding lock 2...");
try { Thread.sleep(10); }
catch (InterruptedException e) {}
System.out.println("Thread 2: Waiting for lock 1...");
synchronized (l1) {
System.out.println("Thread 2: Holding lock 2 & 1...");
}
}
}
}
}
答案 5 :(得分:6)
这是C ++ 11中的一个简单示例。
#include <mutex> // mutex
#include <iostream> // cout
#include <cstdio> // getchar
#include <thread> // this_thread, yield
#include <future> // async
#include <chrono> // seconds
using namespace std;
mutex _m1;
mutex _m2;
// Deadlock will occur because func12 and func21 acquires the two locks in reverse order
void func12()
{
unique_lock<mutex> l1(_m1);
this_thread::yield(); // hint to reschedule
this_thread::sleep_for( chrono::seconds(1) );
unique_lock<mutex> l2(_m2 );
}
void func21()
{
unique_lock<mutex> l2(_m2);
this_thread::yield(); // hint to reschedule
this_thread::sleep_for( chrono::seconds(1) );
unique_lock<mutex> l1(_m1);
}
int main( int argc, char* argv[] )
{
async(func12);
func21();
cout << "All done!"; // this won't be executed because of deadlock
getchar();
}
答案 6 :(得分:5)
请参阅我对this question的回答。只要两个线程需要获取两个不同的资源,并且以不同的顺序执行,那么你就可以获得死锁。
答案 7 :(得分:4)
我能想到的一个例子是桌子,手电筒和电池场景。想象一下手电筒和一对电池放在桌子上面。如果你走到这张桌子上拿着电池,而另一个人拿着手电筒,你会被迫尴尬地盯着对方,等待谁先将他们的物品放回桌子上。这是死锁的一个例子。你和这个人正在等待资源,但你们谁都没有放弃他们的资源。
类似地,在程序中,当两个或多个线程(您和另一个人)正在等待释放两个或更多个锁(手电筒和电池)并且程序中的情况使得锁是永远不会被释放(你们都有一块拼图)。
如果您了解java,则可以使用以下方法来表示此问题:
import java.util.concurrent.locks.*;
public class Deadlock1 {
public static class Table {
private static Lock Flashlight = new ReentrantLock();
private static Lock Batteries = new ReentrantLock();
public static void giveFlashLightAndBatteries() {
try {
Flashlight.lock();
Batteries.lock();
System.out.println("Lights on");
} finally {
Batteries.unlock();
Flashlight.unlock();
}
}
public static void giveBatteriesAndFlashLight() {
try {
Batteries.lock();
Flashlight.lock();
System.out.println("Lights on");
} finally {
Flashlight.unlock();
Batteries.unlock();
}
}
}
public static void main(String[] args) {
// This thread represents person one
new Thread(new Runnable() {
public void run() { Table.giveFlashLightAndBatteries(); }
}).start();
// This thread represents person two
new Thread(new Runnable() {
public void run() { Table.giveBatteriesAndFlashLight(); }
}).start();
}
}
如果你运行这个例子,你会注意到有时事情很好而且正确。但有时你的程序不会打印任何东西。这是因为一个人有电池而另一个人有手电筒,这会阻止他们打开手电筒导致死锁。
此示例类似于java教程给出的示例:http://docs.oracle.com/javase/tutorial/essential/concurrency/deadlock.html
另一个例子是循环示例:
public class Deadlock2 {
public static class Loop {
private static boolean done = false;
public static synchronized void startLoop() throws InterruptedException {
while(!done) {
Thread.sleep(1000);
System.out.println("Not done");
}
}
public static synchronized void stopLoop() {
done = true;
}
}
public static void main(String[] args) {
// This thread starts the loop
new Thread(new Runnable() {
public void run() {
try {
Loop.startLoop();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
// This thread stops the loop
new Thread(new Runnable() {
public void run() {
Loop.stopLoop();
}
}).start();
}
}
此示例可以反复打印“未完成”,或者根本不打印“未完成”。第一个发生是因为第一个线程获取了类锁并且从不释放它,防止第二个线程访问“stopLoop”。最新的情况发生是因为第二个线程在第一个线程之前启动,导致'done'变量在第一个线程执行之前为真。
答案 8 :(得分:3)
我认为Dining Philosophers问题是显示死锁的一个更简单的例子,因为4个死锁要求可以通过绘图(尤其是循环等待)轻松说明。
我认为现实世界的例子对新手来说更加困惑,虽然我现在无法想到一个好的现实世界场景(我对现实世界的并发性相对缺乏经验)。
答案 9 :(得分:3)
public class DeadLock {
public static void main(String[] args) throws InterruptedException {
Thread mainThread = Thread.currentThread();
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
try {
mainThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
thread1.start();
thread1.join();
}
}
答案 10 :(得分:3)
另一个简单的死锁示例,包含两个不同的资源和两个等待彼此释放资源的线程。直接来自 examples.oreilly.com/jenut/Deadlock.java
public class Deadlock {
public static void main(String[] args) {
// These are the two resource objects we'll try to get locks for
final Object resource1 = "resource1";
final Object resource2 = "resource2";
// Here's the first thread. It tries to lock resource1 then resource2
Thread t1 = new Thread() {
public void run() {
// Lock resource 1
synchronized(resource1) {
System.out.println("Thread 1: locked resource 1");
// Pause for a bit, simulating some file I/O or something.
// Basically, we just want to give the other thread a chance to
// run. Threads and deadlock are asynchronous things, but we're
// trying to force deadlock to happen here...
try { Thread.sleep(50); } catch (InterruptedException e) {}
// Now wait 'till we can get a lock on resource 2
synchronized(resource2) {
System.out.println("Thread 1: locked resource 2");
}
}
}
};
// Here's the second thread. It tries to lock resource2 then resource1
Thread t2 = new Thread() {
public void run() {
// This thread locks resource 2 right away
synchronized(resource2) {
System.out.println("Thread 2: locked resource 2");
// Then it pauses, for the same reason as the first thread does
try { Thread.sleep(50); } catch (InterruptedException e) {}
// Then it tries to lock resource1. But wait! Thread 1 locked
// resource1, and won't release it 'till it gets a lock on
// resource2. This thread holds the lock on resource2, and won't
// release it 'till it gets resource1. We're at an impasse. Neither
// thread can run, and the program freezes up.
synchronized(resource1) {
System.out.println("Thread 2: locked resource 1");
}
}
}
};
// Start the two threads. If all goes as planned, deadlock will occur,
// and the program will never exit.
t1.start();
t2.start();
}
}
答案 11 :(得分:3)
我最近意识到情侣之间的争斗只不过是一个僵局......通常其中一个过程必须崩溃来解决它,当然这是次要的优先级(男孩;))。
这是类比......
过程1:女孩(G)过程2:男孩(B)
资源1:抱歉资源2:接受自己的错误
必要条件:
的 1。相互排斥: G或B中只有一个可以一次表示抱歉或接受自己的错误
的 2。等待:一次,一个抱着抱歉和其他接受自己的错误,一个正在等待接受自己的错误释放抱歉,其他等待抱歉释放接受自己的错误。
第3。没有先发制人:甚至上帝都不能强迫B或G释放抱歉或接受自己的错误。并自愿?你在跟我开玩笑吗?
的 4。循环等待:再次,持有抱歉的人等待其他人接受自己的错误,而一个持有接受自己错误的人则要先说对不起。所以它是循环的。
因此,当所有这些条件同时生效时会发生死锁,并且在一场战斗中总是如此;)
来源:http://www.quora.com/Saurabh-Pandey-3/Posts/Never-ending-couple-fights-a-deadlock
答案 12 :(得分:1)
producers-consumers problem和餐饮哲学家的问题可能就像它会得到的一样简单。它有一些伪代码也可以说明它。如果那些对于新手来说过于复杂,他们最好更加努力地抓住它们。
答案 13 :(得分:1)
public class DeadLock {
public static void main(String[] args) {
Object resource1 = new Object();
Object resource2 = new Object();
SharedObject s = new SharedObject(resource1, resource2);
TestThread11 t1 = new TestThread11(s);
TestThread22 t2 = new TestThread22(s);
t1.start();
t2.start();
}
}
class SharedObject {
Object o1, o2;
SharedObject(Object o1, Object o2) {
this.o1 = o1;
this.o2 = o2;
}
void m1() {
synchronized(o1) {
System.out.println("locked on o1 from m1()");
synchronized(o2) {
System.out.println("locked on o2 from m1()");
}
}
}
void m2() {
synchronized(o2) {
System.out.println("locked on o2 from m2()");
synchronized(o1) {
System.out.println("locked on o1 from m2()");
}
}
}
}
class TestThread11 extends Thread {
SharedObject s;
TestThread11(SharedObject s) {
this.s = s;
}
public void run() {
s.m1();
}
}
class TestThread22 extends Thread {
SharedObject s;
TestThread22(SharedObject s) {
this.s = s;
}
public void run() {
s.m2();
}
}
答案 14 :(得分:1)
当Girl1
想与Guy2
调情时,可能会发生死锁,Girl2
被另一个Girl2
抓住,而Guy1
想要调查被Girl1
抓住的class OuchTheGirls
{
public static void main(String[] args)
{
final String resource1 = "Guy1";
final String resource2 = "Guy2";
// Girl1 tries to lock resource1 then resource2
Thread Girl1 = new Thread(() ->
{
synchronized (resource1)
{
System.out.println("Thread 1: locked Guy1");
try { Thread.sleep(100);} catch (Exception e) {}
synchronized (resource2)
{
System.out.println("Thread 1: locked Guy2");
}
}
});
// Girl2 tries to lock Guy2 then Guy1
Thread Girl2 = new Thread(() ->
{
synchronized (resource2)
{
System.out.println("Thread 2: locked Guy2");
try { Thread.sleep(100);} catch (Exception e) {}
synchronized (resource1)
{
System.out.println("Thread 2: locked Guy1");
}
}
});
Girl1.start();
Girl2.start();
}
}
。因为,两个女孩都在等待相互倾倒,这种情况被称为死锁。
for (int i=0; i<9; i++){
y += 50;
x = 160;
for (int j=0; j<9; j++){
grid = [[UITextField alloc] initWithFrame:CGRectMake(x, y, 50 , 50)];
grid.layer.borderWidth = 1;
grid.textAlignment = NSTextAlignmentCenter;
[[self view] addSubview:grid];
x += 50;
grid.text = [@(j) stringValue];
[initialArray addObject:grid];
}
}
答案 15 :(得分:1)
来自https://docs.oracle.com/javase/tutorial/essential/concurrency/deadlock.html
的简单示例public class Deadlock {
public static void printMessage(String message) {
System.out.println(String.format("%s %s ", Thread.currentThread().getName(), message));
}
private static class Friend {
private String name;
public Friend(String name) {
this.name = name;
}
public void bow(Friend friend) {
printMessage("Acquiring lock on " + this.name);
synchronized(this) {
printMessage("Acquired lock on " + this.name);
printMessage(name + " bows " + friend.name);
friend.bowBack(this);
}
}
public void bowBack(Friend friend) {
printMessage("Acquiring lock on " + this.name);
synchronized (this) {
printMessage("Acquired lock on " + this.name);
printMessage(friend.name + " bows back");
}
}
}
public static void main(String[] args) throws InterruptedException {
Friend one = new Friend("one");
Friend two = new Friend("two");
new Thread(new Runnable() {
@Override
public void run() {
one.bow(two);
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
two.bow(one);
}
}).start();
}
}
输出:
Thread-0 Acquiring lock on one
Thread-1 Acquiring lock on two
Thread-0 Acquired lock on one
Thread-1 Acquired lock on two
Thread-1 two bows one
Thread-0 one bows two
Thread-1 Acquiring lock on one
Thread-0 Acquiring lock on two
线程转储:
2016-03-14 12:20:09
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.74-b02 mixed mode):
"DestroyJavaVM" #13 prio=5 os_prio=0 tid=0x00007f472400a000 nid=0x3783 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Thread-1" #12 prio=5 os_prio=0 tid=0x00007f472420d800 nid=0x37a3 waiting for monitor entry [0x00007f46e89a5000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.anantha.algorithms.ThreadJoin$Friend.bowBack(ThreadJoin.java:102)
- waiting to lock <0x000000076d0583a0> (a com.anantha.algorithms.ThreadJoin$Friend)
at com.anantha.algorithms.ThreadJoin$Friend.bow(ThreadJoin.java:92)
- locked <0x000000076d0583e0> (a com.anantha.algorithms.ThreadJoin$Friend)
at com.anantha.algorithms.ThreadJoin$2.run(ThreadJoin.java:141)
at java.lang.Thread.run(Thread.java:745)
"Thread-0" #11 prio=5 os_prio=0 tid=0x00007f472420b800 nid=0x37a2 waiting for monitor entry [0x00007f46e8aa6000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.anantha.algorithms.ThreadJoin$Friend.bowBack(ThreadJoin.java:102)
- waiting to lock <0x000000076d0583e0> (a com.anantha.algorithms.ThreadJoin$Friend)
at com.anantha.algorithms.ThreadJoin$Friend.bow(ThreadJoin.java:92)
- locked <0x000000076d0583a0> (a com.anantha.algorithms.ThreadJoin$Friend)
at com.anantha.algorithms.ThreadJoin$1.run(ThreadJoin.java:134)
at java.lang.Thread.run(Thread.java:745)
"Monitor Ctrl-Break" #10 daemon prio=5 os_prio=0 tid=0x00007f4724211000 nid=0x37a1 runnable [0x00007f46e8def000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:170)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
- locked <0x000000076d20afb8> (a java.io.InputStreamReader)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:161)
at java.io.BufferedReader.readLine(BufferedReader.java:324)
- locked <0x000000076d20afb8> (a java.io.InputStreamReader)
at java.io.BufferedReader.readLine(BufferedReader.java:389)
at com.intellij.rt.execution.application.AppMain$1.run(AppMain.java:93)
at java.lang.Thread.run(Thread.java:745)
"Service Thread" #9 daemon prio=9 os_prio=0 tid=0x00007f47240c9800 nid=0x3794 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C1 CompilerThread3" #8 daemon prio=9 os_prio=0 tid=0x00007f47240c6800 nid=0x3793 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread2" #7 daemon prio=9 os_prio=0 tid=0x00007f47240c4000 nid=0x3792 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread1" #6 daemon prio=9 os_prio=0 tid=0x00007f47240c2800 nid=0x3791 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread0" #5 daemon prio=9 os_prio=0 tid=0x00007f47240bf800 nid=0x3790 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Signal Dispatcher" #4 daemon prio=9 os_prio=0 tid=0x00007f47240be000 nid=0x378f waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00007f472408c000 nid=0x378e in Object.wait() [0x00007f46e98c5000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x000000076cf88ee0> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
- locked <0x000000076cf88ee0> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)
"Reference Handler" #2 daemon prio=10 os_prio=0 tid=0x00007f4724087800 nid=0x378d in Object.wait() [0x00007f46e99c6000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x000000076cf86b50> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:502)
at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
- locked <0x000000076cf86b50> (a java.lang.ref.Reference$Lock)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)
"VM Thread" os_prio=0 tid=0x00007f4724080000 nid=0x378c runnable
"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00007f472401f000 nid=0x3784 runnable
"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00007f4724021000 nid=0x3785 runnable
"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x00007f4724022800 nid=0x3786 runnable
"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x00007f4724024800 nid=0x3787 runnable
"GC task thread#4 (ParallelGC)" os_prio=0 tid=0x00007f4724026000 nid=0x3788 runnable
"GC task thread#5 (ParallelGC)" os_prio=0 tid=0x00007f4724028000 nid=0x3789 runnable
"GC task thread#6 (ParallelGC)" os_prio=0 tid=0x00007f4724029800 nid=0x378a runnable
"GC task thread#7 (ParallelGC)" os_prio=0 tid=0x00007f472402b800 nid=0x378b runnable
"VM Periodic Task Thread" os_prio=0 tid=0x00007f47240cc800 nid=0x3795 waiting on condition
JNI global references: 16
Found one Java-level deadlock:
=============================
"Thread-1":
waiting to lock monitor 0x00007f46dc003f08 (object 0x000000076d0583a0, a com.anantha.algorithms.ThreadJoin$Friend),
which is held by "Thread-0"
"Thread-0":
waiting to lock monitor 0x00007f46dc006008 (object 0x000000076d0583e0, a com.anantha.algorithms.ThreadJoin$Friend),
which is held by "Thread-1"
Java stack information for the threads listed above:
===================================================
"Thread-1":
at com.anantha.algorithms.ThreadJoin$Friend.bowBack(ThreadJoin.java:102)
- waiting to lock <0x000000076d0583a0> (a com.anantha.algorithms.ThreadJoin$Friend)
at com.anantha.algorithms.ThreadJoin$Friend.bow(ThreadJoin.java:92)
- locked <0x000000076d0583e0> (a com.anantha.algorithms.ThreadJoin$Friend)
at com.anantha.algorithms.ThreadJoin$2.run(ThreadJoin.java:141)
at java.lang.Thread.run(Thread.java:745)
"Thread-0":
at com.anantha.algorithms.ThreadJoin$Friend.bowBack(ThreadJoin.java:102)
- waiting to lock <0x000000076d0583e0> (a com.anantha.algorithms.ThreadJoin$Friend)
at com.anantha.algorithms.ThreadJoin$Friend.bow(ThreadJoin.java:92)
- locked <0x000000076d0583a0> (a com.anantha.algorithms.ThreadJoin$Friend)
at com.anantha.algorithms.ThreadJoin$1.run(ThreadJoin.java:134)
at java.lang.Thread.run(Thread.java:745)
Found 1 deadlock.
Heap
PSYoungGen total 74752K, used 9032K [0x000000076cf80000, 0x0000000772280000, 0x00000007c0000000)
eden space 64512K, 14% used [0x000000076cf80000,0x000000076d8520e8,0x0000000770e80000)
from space 10240K, 0% used [0x0000000771880000,0x0000000771880000,0x0000000772280000)
to space 10240K, 0% used [0x0000000770e80000,0x0000000770e80000,0x0000000771880000)
ParOldGen total 171008K, used 0K [0x00000006c6e00000, 0x00000006d1500000, 0x000000076cf80000)
object space 171008K, 0% used [0x00000006c6e00000,0x00000006c6e00000,0x00000006d1500000)
Metaspace used 3183K, capacity 4500K, committed 4864K, reserved 1056768K
class space used 352K, capacity 388K, committed 512K, reserved 1048576K
答案 16 :(得分:1)
这是Java中的一个简单死锁。我们需要两个资源来演示死锁。在下面的示例中,一个资源是类锁(通过同步方法),另一个是整数&#39; i&#39;
public class DeadLock {
static int i;
static int k;
public static synchronized void m1(){
System.out.println(Thread.currentThread().getName()+" executing m1. Value of i="+i);
if(k>0){i++;}
while(i==0){
System.out.println(Thread.currentThread().getName()+" waiting in m1 for i to be > 0. Value of i="+i);
try { Thread.sleep(10000);} catch (InterruptedException e) { e.printStackTrace(); }
}
}
public static void main(String[] args) {
Thread t1 = new Thread("t1") {
public void run() {
m1();
}
};
Thread t2 = new Thread("t2") {
public void run() {
try { Thread.sleep(100);} catch (InterruptedException e) { e.printStackTrace(); }
k++;
m1();
}
};
t1.start();
t2.start();
}
}
答案 17 :(得分:1)
我在阅读餐饮哲学家的问题时发现有点难以理解,僵局IMHO实际上与资源分配有关。 想分享一个更简单的例子,其中2护士需要争取3个装备才能完成任务。 虽然它是用java编写的。创建一个简单的lock()方法来模拟死锁的发生方式,因此它也可以应用于其他编程语言。 http://www.justexample.com/wp/example-of-deadlock/
答案 18 :(得分:1)
选择简单的可能场景,在向学生介绍概念时可能会发生死锁。这将涉及至少两个线程和至少两个资源(我认为)。目标是设计一个场景,其中第一个线程锁定资源1,并等待资源2的锁定被释放,同时线程2持有对资源2的锁定,并且正在等待锁定资源一将被释放。
底层资源是什么并不重要;为了简单起见,你可以让它们成为两个线程都能写入的文件对。
编辑:假设除了持有的锁之外没有进程间通信。
答案 19 :(得分:1)
这是C#中的一个简单死锁。
void UpdateLabel(string text) {
lock(this) {
if(MyLabel.InvokeNeeded) {
IAsyncResult res = MyLable.BeginInvoke(delegate() {
MyLable.Text = text;
});
MyLabel.EndInvoke(res);
} else {
MyLable.Text = text;
}
}
}
如果有一天,你从GUI线程调用它,而另一个线程也调用它 - 你可能会死锁。另一个线程转到EndInvoke,等待GUI线程执行 在拿着锁的同时委托。 GUI线程在同一个锁上阻塞,等待另一个线程释放它 - 它不会因为GUI线程永远不可用于执行另一个线程正在等待的委托。 (当然,这里的锁并不是严格需要的 - 也许也不是EndInvoke,但是在稍微复杂的情况下,调用者可能会因其他原因获取锁定,导致同样的死锁。)
答案 20 :(得分:0)
public class DeadlockProg {
/**
* @Gowtham Chitimi Reddy IIT(BHU);
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
final Object ob1 = new Object();
final Object ob2 = new Object();
Thread t1 = new Thread(){
public void run(){
synchronized(ob1){
try{
Thread.sleep(100);
}
catch(InterruptedException e){
System.out.println("Error catched");
}
synchronized(ob2){
}
}
}
};
Thread t2 = new Thread(){
public void run(){
synchronized(ob2){
try{
Thread.sleep(100);
}
catch(InterruptedException e){
System.out.println("Error catched");
}
synchronized(ob1){
}
}
}
};
t1.start();
t2.start();
}
}
答案 21 :(得分:0)
package ForkBlur;
public class DeadLockTest {
public static void main(String args[]) {
final DeadLockTest t1 = new DeadLockTest();
final DeadLockTest t2 = new DeadLockTest();
Runnable r1 = new Runnable() {
@Override
public void run() {
try {
synchronized (t1) {
System.out
.println("r1 has locked t1, now going to sleep");
Thread.sleep(100);
System.out
.println("r1 has awake , now going to aquire lock for t2");
synchronized (t2) {
Thread.sleep(100);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
};
Runnable r2 = new Runnable() {
@Override
public void run() {
try {
synchronized (t2) {
System.out
.println("r2 has aquire the lock of t2 now going to sleep");
Thread.sleep(100);
System.out
.println("r2 is awake , now going to aquire the lock from t1");
synchronized (t1) {
Thread.sleep(100);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
};
new Thread(r1).start();
new Thread(r2).start();
}
}
答案 22 :(得分:0)
我创建了一个超简单工作死锁示例: -
package com.thread.deadlock;
public class ThreadDeadLockClient {
public static void main(String[] args) {
ThreadDeadLockObject1 threadDeadLockA = new ThreadDeadLockObject1("threadDeadLockA");
ThreadDeadLockObject2 threadDeadLockB = new ThreadDeadLockObject2("threadDeadLockB");
new Thread(new Runnable() {
@Override
public void run() {
threadDeadLockA.methodA(threadDeadLockB);
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
threadDeadLockB.methodB(threadDeadLockA);
}
}).start();
}
}
package com.thread.deadlock;
public class ThreadDeadLockObject1 {
private String name;
ThreadDeadLockObject1(String name){
this.name = name;
}
public synchronized void methodA(ThreadDeadLockObject2 threadDeadLockObject2) {
System.out.println("In MethodA "+" Current Object--> "+this.getName()+" Object passed as parameter--> "+threadDeadLockObject2.getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
threadDeadLockObject2.methodB(this);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package com.thread.deadlock;
public class ThreadDeadLockObject2 {
private String name;
ThreadDeadLockObject2(String name){
this.name = name;
}
public synchronized void methodB(ThreadDeadLockObject1 threadDeadLockObject1) {
System.out.println("In MethodB "+" Current Object--> "+this.getName()+" Object passed as parameter--> "+threadDeadLockObject1.getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
threadDeadLockObject1.methodA(this);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
在上面的示例中,2个线程正在执行两个不同对象的同步方法。 同步方法A由对象threadDeadLockA调用,同步方法B由对象threadDeadLockB调用。在methodA中传递threadDeadLockB的引用,并在方法B中传递threadDeadLockA的引用。现在每个线程都试图锁定另一个对象。在methodA中,对threadDeadLockA持有锁的线程正在尝试锁定对象threadDeadLockB,类似地,在methodB中,对threadDeadLockB持有锁的线程正在尝试锁定threadDeadLockA。因此,两个线程将永远等待造成死锁。
答案 23 :(得分:0)
让我使用超过 2 个线程的示例更清楚地解释一下。
让我们假设您有n个线程,每个线程分别持有锁L1,L2,...,Ln。现在让我们说,从线程1开始,每个线程都试图获取其邻居线程的锁。因此,线程1被阻止以尝试获取L2(因为L2由线程2拥有),线程2被阻塞用于L3,依此类推。线程n被阻塞为L1。现在这是一个死锁,因为没有线程能够执行。
html
在上面的示例中,您可以看到有三个线程持有class ImportantWork{
synchronized void callAnother(){
}
synchronized void call(ImportantWork work) throws InterruptedException{
Thread.sleep(100);
work.callAnother();
}
}
class Task implements Runnable{
ImportantWork myWork, otherWork;
public void run(){
try {
myWork.call(otherWork);
} catch (InterruptedException e) {
}
}
}
class DeadlockTest{
public static void main(String args[]){
ImportantWork work1=new ImportantWork();
ImportantWork work2=new ImportantWork();
ImportantWork work3=new ImportantWork();
Task task1=new Task();
task1.myWork=work1;
task1.otherWork=work2;
Task task2=new Task();
task2.myWork=work2;
task2.otherWork=work3;
Task task3=new Task();
task3.myWork=work3;
task3.otherWork=work1;
new Thread(task1).start();
new Thread(task2).start();
new Thread(task3).start();
}
}
的task1,task2和task3。在语句Runnable
之前,线程在进入sleep(100)
方法时获取三个工作对象的锁(由于存在call()
)。但是一旦他们在邻居线程的对象上尝试synchronized
,它们就会被阻塞,从而导致死锁,因为这些对象的锁已经被锁定了。
答案 24 :(得分:0)
package test.concurrent;
public class DeadLockTest {
private static long sleepMillis;
private final Object lock1 = new Object();
private final Object lock2 = new Object();
public static void main(String[] args) {
sleepMillis = Long.parseLong(args[0]);
DeadLockTest test = new DeadLockTest();
test.doTest();
}
private void doTest() {
Thread t1 = new Thread(new Runnable() {
public void run() {
lock12();
}
});
Thread t2 = new Thread(new Runnable() {
public void run() {
lock21();
}
});
t1.start();
t2.start();
}
private void lock12() {
synchronized (lock1) {
sleep();
synchronized (lock2) {
sleep();
}
}
}
private void lock21() {
synchronized (lock2) {
sleep();
synchronized (lock1) {
sleep();
}
}
}
private void sleep() {
try {
Thread.sleep(sleepMillis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
To run the deadlock test with sleep time 1 millisecond:
java -cp . test.concurrent.DeadLockTest 1
答案 25 :(得分:0)
CountDownLatch countDownLatch = new CountDownLatch(1);
ExecutorService executorService = ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.execute(() -> {
Future<?> future = executorService.submit(() -> {
System.out.println("generated task");
});
countDownLatch.countDown();
try {
future.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
});
countDownLatch.await();
executorService.shutdown();
答案 26 :(得分:0)
只用一个线程来实现死锁的偷偷摸摸的方法是尝试两次锁定相同的(非递归)互斥锁。这可能不是您正在寻找的简单示例,但我确实已经遇到过这种情况。
#include <mutex>
#include <iostream>
int main()
{
std::mutex m;
m.lock();
m.lock();
std::cout << "Expect never to get here because of a deadlock!";
}
答案 27 :(得分:0)
这是我花费大量时间后死锁的详细示例。希望对您有所帮助:)
char name[20]