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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 张凯 中级黑马   /  2012-7-19 20:19  /  2259 人查看  /  4 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

很多资料上都说sleep 不会释放锁.我做了一个小例子,感觉有点晕
  1. public class Test2 extends Thread {

  2.         int b = 100;

  3.         public void m1() throws InterruptedException {
  4.                
  5.                 System.out.println("m1 enter..");
  6.                 synchronized (this) {
  7.                         System.out.println("m1 enter synchronized block..");
  8.                         b = 200;
  9.                         Thread.sleep(5000);//?
  10.                         System.out.println("b= " + b);
  11.                 }
  12.         }

  13.         public  void m2() throws InterruptedException {
  14.                 System.out.println("m2 enter..");
  15.                 b = 500;
  16.         }

  17.         public void run() {
  18.                 System.out.println("runing ...");
  19.                 try {
  20.                         m1();
  21.                 } catch (InterruptedException e) {

  22.                         e.printStackTrace();
  23.                 }
  24.         }

  25.         public static void main(String[] args) throws InterruptedException {
  26.                 Test2 t = new Test2();
  27.                  
  28.                 t.start();

  29.                 Thread.sleep(2000);
  30.                 t.m2();

  31.         }

  32. }

复制代码
输出结果如下:
runing ...
m1 enter..
m1 enter synchronized block..
m2 enter..
b= 500
我怎么感觉最后一行输出 应该是 100呢.还有m1方法进入同步块后居然还执行m2方法了是怎么回事?
如果给m2方法 加 synchronized,结果是我想要的,想不明白....

评分

参与人数 1技术分 +1 收起 理由
刘笑 + 1 赞一个!

查看全部评分

4 个回复

倒序浏览
m2 方法是由 主线程负责执行的
你的 新建线程执行进入代码块后,他将 this 锁关闭其他线程不能进入 有this 锁的 同步代码块

但是你的 m2()方法并没有加上同步,更没有this同步锁, 它 当然是可执行的

你想要的效果是 新线程进入同步块后 其他线程不能操作 b 吧?
那就应该把有 b 操作的地方加上同步,并且使用 this 锁
:synchronized (this) {
         b = 500;
}
回复 使用道具 举报
我用你的代码做的实验:
你的源码结果为:
runing ...
m1 enter..
m1 enter synchronized block..
m2 enter..
b= 500
过程是:
1,主线程启动
2,调用start方法==》runing ...
3,主线程休眠2秒
4,调用m1() ==》m1 enter..
5,m1中进入同步代码块 ==》m1 enter synchronized block..
6,m1中 b=200,睡眠5秒==》
7,主线程苏醒,调用m2()方法 b=500 ==》m2 enter..
8,m1苏醒==》打印b= 500

如果给m2方法 加 synchronized,我的结果是          
runing ...
m1 enter..
m1 enter synchronized block..
b= 200
m2 enter..
过程是:
1,主线程启动
2,调用start方法==》runing ...
3,主线程休眠2秒
4,调用m1() ==》m1 enter..
5,m1中进入同步代码块 ==》m1 enter synchronized block..
6,m1中 b=200,睡眠5秒==》但是不会释放对象锁
7,主线程苏醒,调用m2()方法 (但是没有锁不能运行)
8,m1苏醒==》打印b= 200
9,m2()获得锁运行==》m2 enter..



评分

参与人数 1技术分 +1 收起 理由
刘笑 + 1 赞一个!

查看全部评分

回复 使用道具 举报
本帖最后由 黄丽慧 于 2012-7-20 11:05 编辑

楼主,  Thread.sleep是让当前线程休眠一段时间      
public static void main(String[] args) throws InterruptedException {
                Test2 t = new Test2();
                 
                t.start();//这里t线程启动调用run方法,runing ...,run中调用了M1方法,打印m1 enter..,进入锁之后,打印m1 enter synchronized block..
再往下运行时,楼主调用了一次Thread.sleep方法,此时休眠的是t线程,t线程休眠后,main函数获取cup执行权


                Thread.sleep(2000);//main函数运行到这里时,调用了Thread.sleep,此时休眠的就是main函数了,主线程休眠的时间为2秒,t线程休眠的时间为5秒,因此主线程先获取执行权
                t.m2();//就调用了m2方法,打印m2 enter.. b= 500

        }
如果想要验证sleep的作用,应该创建两个线程,同时去调用m1方法,这样就可以看到锁是不是被释放了。
回复 使用道具 举报
rslheima 发表于 2012-7-19 21:06
我用你的代码做的实验:
你的源码结果为:
runing ...

清楚明白,收藏了...
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马