有如下程序1 public class TT implements Runnable { 
2 int b = 100; 

4 public synchronized void m1() throws Exception{ 
5 b = 1000; 
7 System.out.println("b = " + b); 
8 } 

10 public synchronized void m2() throws Exception { 
11 //Thread.sleep(2500); 
12 b = 2000; 
13 } 
14 
15 public void run() { 
16 try { 
17 m1(); 
18 } catch(Exception e) { 
19 e.printStackTrace(); 
20 } 
21 } 
22 
23 public static void main(String[] args) throws Exception 
24{ 
25 TT tt = new TT(); 
26 Thread t = new Thread(tt); 
27 t.start(); 
28 tt.m2();//先拿到锁? 
30 System.out.println(tt.b); 
31 } 

运行结果 
1.不解开注释,2000 
           b=1000  
3. 解开第11行 1000 
           b=1000 
我的问题是: 
1.解开11行后,为什么就变成先输出2000? 
2. 解开11行后,为什么说m2先拿到锁?
3.解开11行后,如果是m2先拿到锁,那么m2结束时是先运行主线程(System.out.println(tt.b);)还是m1拿到锁运行? 
我在马士兵视频里看的这个,觉得讲的不是很明白,希望有人能把线程给我讲个明明白白!!这个东西我脑子里现在乱成一团!!

解决方案 »

  1.   

    首先,
    Thread.sleep(2500);  这句被注释掉,输出结果是
    2000
    b = 1000
    ----------------------------------
    Thread.sleep(2500); 这句没有被注释掉,输出结果是
    1000
    b = 1000
    ---------------------------------像 public synchronized void m2() 这样对方法加同步,是针对此对象的同步,
    即如果一个线程进入了m2()方法,则被定义为public synchronized void m1()的方法,就要等待
    m2结束了,锁释放了才能进入执行。1.Thread.sleep(2500); 被注释掉的时候,
    在main方法里,虽然是先调用的t.start();
    但是run方法并不会马上执行,需要一定时间来启动执行。
    而此时 执行了:
    tt.m2();
    System.out.println(tt.b);
    b马上被赋值为2000,然后释放了锁,打印输出2000,
    之后才走run方法,又调用了m1方法,输出了b=10002.不管11行是否被注释掉,m2都是先拿到锁。只是当11行没有被注释掉的时候,m2拿到了锁,然后
    调用了Thread.sleep(2500); 并没有马上给b赋值为2000
    而sleep方法不会释放对象锁,所以m2在sleep的过程中依然持有锁。而利用这个时间,线程已经启动,已经执行了run方法,但调用m1的时候,发现没有锁,
    就阻塞了。所以你执行的时候会等一会,发现控制台什么都没有输出。所以当m2退出,释放了锁,m1立即执行了,所以输出的就是
    1000
    b=1000
    3.m2结束时是先运行主线程(System.out.println(tt.b);)还是m1拿到锁运行?这个不一定。
    但是
    System.out.println(tt.b); 和 m1之间没有同步约束。
      

  2.   

    也就是说类似“m2结束时到底先运行主线程(System.out.println(tt.b);)还是m1拿到锁运行”具有不确定性?具体想让哪一个运行需要人为干预?
    run方法的“迟钝时间”能让
    tt.m2(); 
    System.out.println(tt.b); 都运行完毕?但当m2中一睡眠,run才调用了m1,开始等待锁?可不可以认为m1只要被调用了,即使阻塞,只要另一个线程释放了锁,m1保证第一个运行?