A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© volvoxc 中级黑马   /  2014-2-25 12:21  /  1049 人查看  /  9 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

这段小程序,我不明白为什么三个线程都能拿到obj1的锁,而都又拿不到obj2的锁,快速的黑马同学们,谁能给解释一下啊
  1. public class Test {

  2.     public static void main(String[] args) throws InterruptedException {
  3.         Object obj1 = new Object();
  4.         Object obj2 = new Object();
  5.         Object obj3 = new Object();

  6.         Thread t1 = new Thread(new SyncThread(obj1, obj2), "t1");
  7.         Thread t2 = new Thread(new SyncThread(obj2, obj3), "t2");
  8.         Thread t3 = new Thread(new SyncThread(obj3, obj1), "t3");

  9.         t1.start();
  10.         Thread.sleep(1000);
  11.         t2.start();
  12.         Thread.sleep(1000);
  13.         t3.start();

  14.     }

  15. }

  16. class SyncThread implements Runnable{
  17.     private Object obj1;
  18.     private Object obj2;

  19.     public SyncThread(Object o1, Object o2){
  20.         this.obj1=o1;
  21.         this.obj2=o2;
  22.     }
  23.     @Override
  24.     public void run() {
  25.         String name = Thread.currentThread().getName();
  26.         synchronized (obj1) {
  27.          System.out.println(name + "进入obj1 ");
  28.          work();
  29.                  System.out.println(name + "苏醒过来了 ");
  30.          synchronized (obj2) {
  31.             System.out.println(name + " 进入obj2 ");
  32.             work();
  33.         }
  34.          System.out.println(name + " 出obj2 ");
  35.         }
  36.         System.out.println(name + " 出obj1 ");
  37.         System.out.println(name + " 结束");
  38.     }
  39.     private void work() {
  40.         try {
  41.             Thread.sleep(3000);
  42.         } catch (InterruptedException e) {
  43.             e.printStackTrace();
  44.         }
  45.     }
  46. }
复制代码



评分

参与人数 1技术分 +1 收起 理由
zzkang0206 + 1

查看全部评分

9 个回复

倒序浏览
我的运行结果是
t1进入obj1
t2进入obj1
t3进入obj1
t1苏醒过来了
t2苏醒过来了
t3苏醒过来了
然后程序就一直等待了。。。
回复 使用道具 举报
你这个明显互相占着资源,死锁了啊。
t1拿到obj1然后等待一会,这时候t2拿到obj2等待,t3拿到obj3等待
然后t1苏醒要拿obj2结果锁被t2拿了,阻塞了
      t2苏醒要拿obj3结果锁被t3拿了,阻塞了
      t3苏醒要拿obj1结果锁被t1拿了,阻塞了
所以三个线程全挂了。
你至少要让一个如果阻塞的话,释放自己拿到的锁。

评分

参与人数 1技术分 +1 收起 理由
zzkang0206 + 1

查看全部评分

回复 使用道具 举报
薛旻 发表于 2014-2-25 13:47
你这个明显互相占着资源,死锁了啊。
t1拿到obj1然后等待一会,这时候t2拿到obj2等待,t3拿到obj3等待
然后 ...

t1,t2,t3拿的是同一个锁吗
回复 使用道具 举报
Thread t1 = new Thread(new SyncThread(obj1, obj2), "t1");
Thread t2 = new Thread(new SyncThread(obj2, obj3), "t2");
Thread t3 = new Thread(new SyncThread(obj3, obj1), "t3");
你写的代码里传入的三个对象obj1,obj2,obj3就是三个锁,t1,t2,t3操作就是这三个锁
回复 使用道具 举报
薛旻 发表于 2014-2-25 14:06
Thread t1 = new Thread(new SyncThread(obj1, obj2), "t1");
Thread t2 = new Thread(new SyncThread(obj2 ...

明白了。3ku
回复 使用道具 举报
薛旻 中级黑马 2014-2-25 14:18:32
7#
本帖最后由 薛旻 于 2014-2-25 14:19 编辑

我说的锁就是在
synchronized(锁){

}你传入了obj1,obj2,obj3
JDK1.5 有一个接口Lock 和 Condition 替代了synchronized 和 Object的阻塞唤醒方法,常识新的特性吧,前提是弄懂synchronized同步
回复 使用道具 举报
你这个程序死锁吗?你的run()方法中要有
if(flag==true)
{
  synchronized(obj1)   
{     synchronized(obj2)
      {         }  
}               
}
else(flag==false)
{
  synchronized(obj2)   
{     synchronized(obj1)
      {         }  
}               
}
让两个线程,一个执行if(),另一个执行else(),它们个自执行都要彼此的锁,就会死锁啦



评分

参与人数 1技术分 +1 收起 理由
zzkang0206 + 1

查看全部评分

回复 使用道具 举报
很简单,3个线程(A,B,C),A拿了obj1锁,一B拿到了obj2锁。A要用到obj2锁,B不放,B要用到obj1锁,A不放,就会导致死锁。

评分

参与人数 1技术分 +1 收起 理由
zzkang0206 + 1

查看全部评分

回复 使用道具 举报
主线程--t1(线程)开始---锁obj1---打印(t1进入obj1)
t1线程“睡眠3秒”
-----------------------------------------
主线程--t2(线程)开始---锁obj2---打印(t2进入obj1)
t2线程“睡眠3秒”[t1线程还有2秒醒]
-----------------------------------------
主线程--t3(线程)开始---锁obj3---打印(t3进入obj1)
t3线程“睡眠3秒”[t1线程还有1秒醒][t2线程还有2秒醒]
-----------------------------------------
[t1线程醒了][t2线程还有1秒醒][t3线程还有2秒醒]
t1(线程)打印(t1苏醒过来了),此时要进入obj2锁的代码块,但obj2还锁着
-----------------------------------------
[t2线程醒了][t3线程还有1秒醒]
t2(线程)打印(t2苏醒过来了),此时要进入obj2锁的代码块,但obj2还锁着
-----------------------------------------
[t3线程醒了]
t3(线程)打印(t3苏醒过来了),此时要进入obj2锁的代码块,但obj2还锁着
-----------------------------------------

obj2一直锁着锁着,所以都进不了。
如果将Thread.sleep(3000);改成小一点的数值就可以了。如Thread.sleep(10);

评分

参与人数 1技术分 +1 收起 理由
zzkang0206 + 1

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马