package DeadLock;
public class Test01 {
public static void main(String[] args) {
Object o1 = new Object();
Object o2 = new Object();
//两个线程共享o1,o2
MyThread a = new MyThread(o1,o2);
MyThread02 b = new MyThread02(o1,o2);
a.start();
b.start();
//问:为什么可以正常执行?a或者b可能先执行,将o1,o2锁住后,立马就释放了
//然后另一个程序就开始锁o1,o2了,这样是可以正常执行
/**
* 问题1:为什么是o1,o2,o2,o1的上锁形式,不是o1,o2,o1,o2呢?
* 如果是o1,o2,o1,o2的形式,即使是都睡了
* 那也不影响,因为a中的o1,睡醒后,去锁o2,这个时候b要锁o1,o1已被a占了
* 只能等到a中的o1,锁了o2后再将o2,o1释放,b就可以进行锁了(睡不睡无所谓)
* 而如果是o1,o2,o2,o1的形式,如果两个都睡了
* 好家伙,a先把o1给锁了,醒了要锁o2,但b已经把o2锁了,醒了要找o1,两把锁都找不到
* 尴尬了,都停在锁池里面,找锁
* 问题2:为什么o1,o2,o2,o1的形式,不睡的话可以正常执行呢?
* 这其实是a.start()执行后,很快啊,就把o1,o2给锁了,然后又释放了
* 等到b.start()执行后,run方法里,去找锁时,就能找到了
*
* 问题3:为什么这种死锁的形式,当只有一个线程睡眠的时候,有时会成死锁,有时不会呢?
* 这和它的代码是有关系的:如 a.start();
* b.start();
* 这样的话,如果a的run方法中没有睡眠的话,b中有睡眠也可以的,不会造成死锁的
* 但是如果将b.start()放在上面的话,就会造成死锁的,因为b虽然先执行run方法
* 但是睡了1000毫秒,而a.start()在这1000毫秒内早执行了,b睡醒后,要锁o1
* 但o1已经被a锁住了,而a想找o2,但b先执行的,没睡之前就给o2锁住了,所以成了死锁。
*
* 结论:synchronized最好不要在开发中嵌套使用,一不小心就会发生死锁,不好调试
*/
}
}
class MyThread extends Thread{
Object o1;
Object o2;
public MyThread(Object o1,Object o2){
this.o1 = o1;
this.o2 = o2;
}
@Override
public void run() {
synchronized(o1){
/* try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}*/
synchronized (o2){
}
}
}
}
class MyThread02 extends Thread{
Object o1;
Object o2;
public MyThread02(Object o1, Object o2) {
this.o1 = o1;
this.o2 = o2;
}
@Override
public void run() {
synchronized (o2){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (o1){
}
}
}
}
ACAC 死锁(synchronized嵌套)
猜你喜欢
转载自blog.csdn.net/qq_44707513/article/details/110749400
今日推荐
周排行