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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 sanguodouble1 于 2014-3-6 19:28 编辑

刚才在网上看到一道关于同步线程的笔试题,
自己整理如下
  1. package Luntai;

  2. //直接将此类定义为线程类
  3. public class Test1 implements Runnable {
  4. //        一个成员变量
  5.         int b = 100;
  6.         
  7. //        不多说,重写run()
  8.         public void run() {
  9.                 m1();
  10.         }
  11.         
  12.         public synchronized void m1() {
  13.                 b = 1000;
  14. //                等个5秒
  15.                 try {
  16.                         Thread.sleep(5000);
  17.                 } catch (InterruptedException e) {
  18.                         e.printStackTrace();
  19.                 }
  20.                 System.out.println("m1方法输出" + b);
  21.         }
  22.         
  23.         public void m2() {
  24.                 System.out.println("m2方法输出" + b);
  25.         }
  26.         
  27.         public static void main(String[] args) {
  28.                 Test1 mt = new Test1();
  29.                 Thread tt = new Thread(mt);
  30. //                用tt线程调m1方法
  31.                 tt.start();
  32.                
  33. //                等个半秒,确保tt拿到了同步锁
  34.                 try {
  35.                         Thread.sleep(500);
  36.                 } catch (InterruptedException e) {
  37.                         e.printStackTrace();
  38.                 }
  39.                
  40. //                然后用主线程调用m2方法               
  41.                 mt.m2();
  42.                
  43.         }
  44. }
复制代码

问,程序的输出结果?

自己分析了下有3种可能
1.
m2方法输出1000
m1方法输出1000

2.
m2方法输出100
m1方法输出1000

3.在m1执行完前m2不能执行,所以是
m1方法输出1000
m2方法输出1000


由于同步学的比较久了,很多都忘了,坐等详见,另外自己查资料中
自我补充:如果方法m2也加上synchronized关键字,答案又是怎么样的呢?

评分

参与人数 1技术分 +1 收起 理由
何伟超 + 1

查看全部评分

3 个回复

倒序浏览
我看三种都有可能,但那时数学上的概率,计算机实现不了
回复 使用道具 举报
没人解答,自我解答
查了下资料+温习了一下,现整理关于同步线程的一些知识点如下:1.
synchronized锁定的不是方法,而是当前对象,包括成员变量
什么时候解开呢?就是在加锁的大括号执行完后
wait()和sleep()最大的区别:sleep()方法不会释放当前对象的同步锁,而wait()方法会释放同步锁

2.
死锁的预防:
a.逻辑上的预防
b.加大锁的粒度,也就是大家要锁的对象范围

3.
Thread.sleep()睡眠的是当前正在执行的线程

4.
在一个线程正在执行一个对象的synchronized的方法时,其他线程仍然可以执行这个对象的非synchronized方法(这个就是说,在执行同步方法时,需要得到这个对象的同步锁;但对于非同步方法,就没这个要求了)

5.
在一个对象调用notify()方法的时候,当前对象的监听线程正持有同步锁,因此,虽然其他线程被叫醒了,但仍然需要等这个线程执行完synchronized语句块后,释放锁后,其他线程才能公平争夺同步锁。
也就是说,调用wait()语句后,马上释放锁,后面的语句都不会被执行(直到被叫醒)
而在notify()语句后面,一直会执行完synchronized语句块后才会释放同步锁

--------------------------------------------------------------------------------------------------------------
那么,这题显而易见,用到了第4个知识点
解释一下:线程 tt.start();在调用m1方法时取得了这个对象的同步锁,并且将b的值改为1000,然后睡了5秒。
在线程tt睡觉的时候,主线程调用了m2方法,由于m2方法并不是同步方法,所以主线程不需要去获得对象同步锁就能执行,所以先输出m2方法里的语句
也是就是:“m2方法输出1000”
然后tt线程睡醒了,接着再输出"m1方法输出1000",也就是原题的答案是第一种可能。

然后分析我自己的补充题:
前面一样,但是在主线程调用m2方法时,由于m2方法也变成了同步方法,所以主线程需要取得当前对象的同步锁才能执行m2方法,而此时的同步锁
被正在睡觉的m1霸占着,所以,m2方法只能等m1执行完释放同步锁后才能接着执行
也就是输出的答案是
m1方法输出1000
m2方法输出1000

回复 使用道具 举报
本帖最后由 sanguodouble1 于 2014-3-6 09:01 编辑

1楼的兄弟可能没看仔细,这个不是概率问题,不信你自己去运行,结果都是一样的

楼上是我自己的一些分析,如有不当,欢迎指正如果没什么疑问的话,我晚上结题了
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马