这是代码
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并执行,如果这是正确的,这将如何成为死锁情况..我想知道这些线程的执行
答案 0 :(得分:1)
当您启动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
上的锁定,但这些锁定已经被获取,因此它们将等到锁定持有者释放它。锁定持有者永远不会释放它,因为它等待其他资源,所以这个程序永远不会停止。这是经典的僵局。
答案 1 :(得分:0)
我已经了解到,为了防止死锁,您需要使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) {}
}
}
}
};
答案 2 :(得分:0)
这个t1.start()和t2.start()是按顺序写的,所以 我的疑问是线程都是以相同与否或t1开始 启动,执行然后进入t2并执行
对start()
的调用无法确保线程立即启动 。本机调用是通过start0()
进行的,它调用操作系统来分叉一个线程。所以,基本上,thread2可以在thread1之前启动。您无法控制首先启动哪个线程。
这是如何成为僵局的情况
此处存在死锁的可能性,因为t1
可能会锁定resource1
而t2
可能会同时锁定resource2
时间。现在,两个线程都希望另一个线程拥有该资源。因此,你有一个僵局。
因此,作为一种标准做法,t1
和t2
都应该锁定相同的序列。
答案 3 :(得分:0)
sleep()保证t1和t2在进入第二个锁之前获得第一个锁。无论哪个线程先运行。
答案 4 :(得分:0)
“所以我的怀疑是线程开始是否相同或t1开始,执行然后进入t2并执行”
仅仅因为线程t1和t2是顺序生成的,并不意味着它们按顺序执行。线程用于并行执行工作单元。
由于代码中的sleep方法调用,它会因为
而死锁t1获得R1或t2获得t2。订单不确定
两个线程在获取各自的资源后休眠10秒钟,因此我们可以高度肯定地说这两个线程在另一个线程的休眠期间的某个时刻获得了资源。
当t1或t2唤醒并尝试获取第二个资源时,它将被相应的线程兄弟所拥有,它将阻塞。两个线程都将阻止尝试获取另一个持有的资源。
仅出现此情况,因为线程并行执行,而不是按顺序执行。
请参阅http://docs.oracle.com/javase/tutorial/essential/concurrency/deadlock.html
答案 5 :(得分:0)
未定义线程执行的顺序。
您的程序很有可能陷入僵局。但是你可以稍微改变第二个线程中的锁定顺序以避免死锁。我已修改并在下面给出。这又取决于你要编写的逻辑。
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");
}
}
}
};