Java 为什么这不会导致死锁
为什么下面的代码不会导致死锁 从我对多线程编程的有限理解来看,当调用Java 为什么这不会导致死锁,java,deadlock,synchronized,Java,Deadlock,Synchronized,为什么下面的代码不会导致死锁 从我对多线程编程的有限理解来看,当调用getBar1()时,sharedBuffer将被“锁定”,因此,当该方法尝试调用getBar2()时,线程将不得不等待sharedBuffer(由自身持有!)。换句话说,getBar2()无法返回,直到getBar1()完成(并释放了sharedBuffer)。但另一方面,getBar1()也无法返回,因为它正在等待getBar2()返回 ==>死锁。(但事实并非如此,这也是我感到困惑的原因) Java的监视器是递归的,这意味
getBar1()
时,sharedBuffer
将被“锁定”,因此,当该方法尝试调用getBar2()
时,线程将不得不等待sharedBuffer
(由自身持有!)。换句话说,getBar2()
无法返回,直到getBar1()
完成(并释放了sharedBuffer
)。但另一方面,getBar1()
也无法返回,因为它正在等待getBar2()
返回
==>死锁。(但事实并非如此,这也是我感到困惑的原因)
Java的监视器是递归的,这意味着同一线程可以多次获取相同的锁 从JLS()中: 线程t可以多次锁定特定监视器;每次解锁都会反转一次锁定操作的效果
当并发操作试图以不同的顺序锁定两个或多个资源时,会发生死锁,并且它们都被困在等待另一个锁定的资源 例如,线程T1和T2在资源R1和R2上同步:
- T1在R1上同步
- 调度程序决定T2应该运行
- T2在R2上同步
- T2尝试在R1上同步;它被迫等待T1释放锁
- 调度程序发现T2无法继续运行,所以允许T1运行
- T1尝试在R2上同步;它被迫等待T2释放锁
- 两个线程都不能继续
这里所做的是基本的同步,一次只允许一个对象访问sharedBuffer。它不会死锁,因为实际上只有一个锁。在这两个函数中,您都锁定了sharedBuffer。当第一个线程调用getBar1()时,它会锁定sharedBuffer。当同一个线程调用getBar2()时,它会命中synchronized块,并且已经有了锁,所以它只是进入了锁
public class Deadlock extends Thread
{
private Deadlock other;
private String name;
public static void main(String[] args)
{
Deadlock one = new Deadlock("one");
Deadlock two = new Deadlock("two");
one.setOther(two);
two.setOther(one);
one.start();
two.start();
}
public setOther(Deadlock other){ this.other = other; }
public void run() {
deadlock();
}
public synchronized deadlock() {
System.out.println("thread " + this.name + " entering this.deadlock()");
sleep(1000); // adjust as needed to guarantee deadlock
System.out.println("thread " + this.name + " calling other.deadlock()");
other.deadlock(this.name);
System.out.println(name + " - deadlock avoided!");
}
}
如果要导致死锁,请使用两个要锁定的不同值。然后,只有在计时正确的情况下,你才能看到它。如果要强制死锁,请确保第一个线程休眠足够长的时间,以便第二个线程获得锁
下面是一些将死锁的代码。。。(未经测试,prolly有打字错误)。这应该是可行的,因为与需要锁的线程不同的线程具有锁
public class Deadlock extends Thread
{
private Deadlock other;
private String name;
public static void main(String[] args)
{
Deadlock one = new Deadlock("one");
Deadlock two = new Deadlock("two");
one.setOther(two);
two.setOther(one);
one.start();
two.start();
}
public setOther(Deadlock other){ this.other = other; }
public void run() {
deadlock();
}
public synchronized deadlock() {
System.out.println("thread " + this.name + " entering this.deadlock()");
sleep(1000); // adjust as needed to guarantee deadlock
System.out.println("thread " + this.name + " calling other.deadlock()");
other.deadlock(this.name);
System.out.println(name + " - deadlock avoided!");
}
}
阅读有关重入锁的信息。Java中本机的是。啊,所以
getBar1()
正在访问sharedBuffer
这一事实并不能阻止它调用getBar2()
,它也将访问sharedBuffer
?但是如果其他线程试图调用getBar2()
,它将阻塞,直到这一次调用完成为止?@onetwotree:是的。Okie,知道了。谢谢我只是不知道“一个线程可以多次获得相同的锁”。这很有帮助!!:)