[英]java code for deadlock situation?
这是代码
public class TestDeadlockExample1 {
public static void main(String[] args) {
final String resource1 = "xyz";
final String resource2 = "pqr";
// t1 tries to lock resource1 then resource2
Thread t1 = new Thread() {
public void run() {
synchronized (resource1) {
System.out.println("Thread 1: locked resource 1");
try { Thread.sleep(10000);} catch (Exception e) {}
synchronized (resource2) {
System.out.println("Thread 1: locked resource 2");
}
}
}
};
// t2 tries to lock resource2 then resource1
Thread t2 = new Thread() {
public void run() {
synchronized (resource2) {
System.out.println("Thread 2: locked resource 2");
try { Thread.sleep(10000);} catch (Exception e) {}
synchronized (resource1) {
System.out.println("Thread 2: locked resource 1");
}
}
}
};
t1.start();
t2.start();
System.out.println("completed");
}
}
here
t1.start();
t2.start();
System.out.println("completed");
这里
在此t1.start()和t2.start()中是按顺序编写的,所以我怀疑这两个线程是否以相同的方式启动,或者t1开始,执行然后到达t2并执行(如果正确),这怎么会变成死锁情况..我想知道这些线程的执行情况
启动Java程序时,JRE产生主线程,并且该主线程执行您的main
方法。
当您调用t1.start()
,新线程会生成并执行第一个匿名类的run
方法。 从这时起,程序中将同时执行2个线程:“主线程”和“线程1”。
当您调用t2.start()
,另一个线程会生成并执行第二个匿名类的run
方法。 从这时起,程序中将同时执行3个线程:“主线程”,“线程1”,“线程2”。
未定义线程的执行顺序。 可能是任何东西。 通常,它们是同时执行的。
您的“线程1”和“线程2”分别获得对resource1
和resource2
锁定,并睡眠10秒钟。 在这种情况下,您的“主”线程完成了执行。 但是您的程序中还有2个线程,因此当main
方法完成时,程序尚未完成。
在休眠“线程1”和“线程2”之后,尝试获取resource 2
和resource 1
锁,但是这些锁已经被获取,因此它们将等待直到锁持有者将其释放。 锁持有者将永远不会释放它,因为它等待其他资源,因此该程序永远不会停止。 那是典型的僵局情况。
我了解到,要防止死锁,您需要使synchronized
块保持一致。
public void run() {
synchronized (resource1) {
synchronized (resource2) {
System.out.println("Thread 1: locked resource 1");
System.out.println("Thread 1: locked resource 2");
try { Thread.sleep(10000);} catch (Exception e) {}
}
}
}
和
Thread t2 = new Thread() {
public void run() {
synchronized (resource1) {
synchronized (resource2) {
System.out.println("Thread 2: locked resource 2");
System.out.println("Thread 2: locked resource 1");
try { Thread.sleep(10000);} catch (Exception e) {}
}
}
}
};
在此t1.start()和t2.start()是按顺序编写的,因此我的疑问是两个线程是否以相同的方式启动,或者t1开始,执行然后进入t2并执行
调用start()
不能确保Thread 立即启动。 通过start0()
进行本机调用,然后调用OS派生线程。 因此,基本上,线程2可以在线程1之前启动。 您无法控制哪个线程首先启动。
这如何成为僵局
这里存在死锁的可能性,因为t1
可能同时锁定resource1
而t2
可能同时锁定resource2
。 现在,两个线程都希望另一个线程拥有该资源。 因此,您将陷入僵局。
因此,作为标准做法, t1
和t2
都应以相同的顺序获得锁定。
sleep()保证t1和t2都先获得第一把锁,然后再进行第二把锁。 无论哪个线程先运行。
“所以我怀疑这两个线程是否在同一时间启动,或者t1启动,执行然后到t2并执行”
仅仅因为线程t1和t2是顺序生成的,并不意味着它们是顺序执行的。 线程用于并行执行工作单元。
由于代码中的sleep方法调用,它将死锁,因为
t1获取R1或t2获取t2。 顺序不确定
两个线程在获取各自的资源后都会休眠10秒钟,因此在本示例中可以肯定地说,两个线程在另一个的睡眠期间的某个时间点已获取了资源。
当t1或t2唤醒并尝试获取第二资源时,该资源已被同级线程占用,它将阻塞。 两个线程都将阻止尝试获取另一个线程所拥有的资源。
仅因为线程并行执行而不是顺序执行,才会发生这种情况。
请参阅http://docs.oracle.com/javase/tutorial/essential/concurrency/deadlock.html
未定义线程执行的顺序。
您的程序陷入死锁的风险很高。 但是您可以稍微更改第二个线程中的锁定顺序,以避免死锁。 我已经修改并在下面给出。 同样,这取决于要编写的逻辑。
Thread t2 = new Thread() {
public void run() {
synchronized (resource1) {
System.out.println("Thread 2: locked resource 2");
try { Thread.sleep(10000);} catch (Exception e) {}
System.out.println("Thread 2: Waiting for resource 1...");
synchronized (resource2) {
System.out.println("Thread 2: locked resource 1 and 2");
}
}
}
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.