首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > JAVA > J2SE开发 >

一个死锁的实例,关于管程(锁)的疑问。小弟我太晕了。

2012-01-06 
一个死锁的实例,关于管程(锁)的疑问。我太晕了。。// 程序的目的是出死锁class A {synchronized void foo(B b

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


不能在同一时间每个线程都进入自己的管程?)
你所说的“自己的隐式管程”一个对象只有一个,所有的线程都使用它

4、“一个拥有管程的线程如果愿意的话可以再次进入相同的管程。( ”拥有管程不就是在管程里面吗,
再次进入怎么理解?)
同一线程可以递归获得锁。

[解决办法]
楼上说得不错了,不过听管程怎么那么别捏~ - -

造成死锁原因很简单,就是两个拥有锁的线程同时又想获得对方所占之锁

3、“在给定的时间,仅有一个线程可以获得管程。”(既然每个对象都拥有自己的隐式管程为什么
不能在同一时间每个线程都进入自己的管程?)
线程当然可以进入未被占用锁的对象临界区,所以只有一个线程可以进入,对于同一个对象锁只有一把

4、“一个拥有管程的线程如果愿意的话可以再次进入相同的管程。( ”拥有管程不就是在管程里面吗,
再次进入怎么理解?)
这个可以说是句废话,在没有竞争的情况下弃锁后再争锁没理由不被允许吧?只是在有其它线程共同竞争的情况下,鹿获谁手就未必了
[解决办法]
上面说错了,有锁的情况下当然可以再次进入
[解决办法]
你理解的没错 
有时间可以看看<<java thread>>这本书

热点排行