日期:2014-05-20  浏览次数:20666 次

一个死锁的实例,关于管程(锁)的疑问。我太晕了。。
// 程序的目的是出死锁
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、“在给定的时间,仅有一个线程可以获得管程。”(既然每个对象都拥有自己的隐式管程为什么