一个死锁的实例,关于管程(锁)的疑问。我太晕了。。
// 程序的目的是出死锁
class A {
synchronized void foo(B b) {
String name = Thread.currentThread().getName();
System.out.println(name + " entered A.foo");
try {
Thread.sleep(1000);
} catch(Exception e) {
System.out.println("A Interrupted");
}
System.out.println(name + " trying to call B.last()");
b.last();
}
synchronized void last() {
System.out.println("Inside A.last");
}
}
class B {
synchronized void bar(A a) {
String name = Thread.currentThread().getName();
System.out.println(name + " entered B.bar");
try {
Thread.sleep(1000);
} catch(Exception e) {
System.out.println("B Interrupted");
}
System.out.println(name + " trying to call A.last()");
a.last();
}
synchronized void last() {
System.out.println("Inside B.last");
}
}
class Deadlock implements Runnable {
A a = new A();
B b = new B();
Deadlock() {
Thread.currentThread().setName("MainThread");
Thread t = new Thread(this, "RacingThread");
t.start();
a.foo(b); // get lock on a in this thread.
System.out.println("Back in main thread");
}
public void run() {
b.bar(a); // get lock on b in other thread.
System.out.println("Back in other thread");
}
public static void main(String args[]) {
new Deadlock();
}
}
//==========================================================
a.foo(b)调用类A的方法foo,此时foo进入管程(而不是A的last进入管程),延时1秒后由foo调用类B的方法last()(此时B的
last进入管程)。
在A的foo休眠期间,b.bar(a)调用类B的方法bar,此时bar进入管程(而不是B的last进入管程),延时1秒后由bar调用类A的
方法last()(此时A的last进入管程)。
程序执行结果是在foo和bar调用对方类的last()方法成功之前就进入死锁了,两个last()为什么都要加synchronized。foo和bar之
间没有发生互相调用啊为什么要加synchronized修饰,他们调用的是对方类里的last(),这两个last()与各自类里的foo与bar方
法没有任何联系,为什么会出死锁。
为什么4个synchronized缺一不可。
难道一个方法进入管程同类的其它方法也同时进入管程?
============================================================
以下是书上的几句话,我很不理解,希望高手帮我解疑:
1、“每个对象都拥有自己的隐式管程,当对象的同步方法被调用时管程自动载入。”
2、一旦一个线程包含在一个同步方法中,没有其他线程可以调用相同对象的同步方法。
3、“在给定的时间,仅有一个线程可以获得管程。”(既然每个对象都拥有自己的隐式管程为什么
不能在同一时间每个线程都进入自己的管程?)
4、“一个拥有管程的线程如果愿意的话可以再次进入相同的管程。( ”拥有管程不就是在管程里面吗,
再次进入怎么理解?)
这两天也找了很多关于管程(有的叫锁)的文章,还是无法解决心里的疑问,真郁闷啊。。。
------解决方案--------------------
这里synchronized 关键字是获得对象锁
首先A.foo(B)调用的时候就获得了A的锁 在方法返回前不会释放
然后B.foo(A)调用的是有会获得B的锁 在返回前也不会释放
过了sleep之后 A会调用B.last()方法 由于也是synchronized方法 所以需要获得B的锁
B调用A.last()方法也是这样。
相当于A和B都拥有自己的锁不释放,又要获得对方的锁,就造成死锁了
------解决方案--------------------
1、“每个对象都拥有自己的隐式管程,当对象的同步方法被调用时管程自动载入。”
可以理解为这个对象的锁
2、一旦一个线程包含在一个同步方法中,没有其他线程可以调用相同对象的同步方法。
由于获得的是对象锁 所以同一时间只能有一个线程访问带synchronized关键字的方法
3、“在给定的时间,仅有一个线程可以获得管程。”(既然每个对象都拥有自己的隐式管程为什么