public class TT implements Runnable {
int b = 100;

public synchronized void m1() {
b = 1000;
System.out.println("b = " + b);
}

public synchronized void m2() throws Exception {
Thread.sleep(1000);
b = 2000;
}

public void run() {
m1();
}

public static void main(String[] args) throws Exception {
TT tt = new TT();
Thread t = new Thread(tt);
t.start();

tt.m2();
System.out.println(tt.b);
}
}

解决方案 »

  1.   

    如果用DeBug模式结果:2000
    b = 1000
    它是先运行m2方法把b=2000带到main方法中打印b,接着在运行run方法到m1方法中。正常运行模式的结果是:1000
      b=1000
    它是先运行m2后直接运行run方法接着到m1方法中在到main方法把b打印出来b=1000; 
      

  2.   

    当程序执行到t.start()时,可能main线程的时间片没有结束,于是就继续执行tt.m2(),因为m2()加了synchronized加上sleep时是不释放锁的,所以t.start()要等待到锁释放后才能运行所以程序的执行流程相当与先调用m2方法,然后再调用m1方法
      

  3.   

    结果是不确定的,我这还b = 1000  1000呢。
    原因是m1、m2都是sychronized方法,同一个时刻,只允许一个线程访问一个对象中的一个sychronized方法(例如有线程访问m1的时候,其他线程请求访问该对象的m2也不行)。那么输出的结果就跟线程的推进顺序有关了,主线程时间片没有结束,执行到tt.m2(),此时新建的线程就算执行到run()中访问m1,也会等待主线程执行完了m2,才能够执行m1,结果这两步完了后b还是等于1000.而后是1000 b=1000还是b=1000 1000跟线程的推进执行println的顺序有关,两种结果都是可能的。另一种可能的结果是子线程推进比主线程快,执行到了run中的m1,则会阻塞主线程访问m2,子线程执行完m1后主线程才能访问m2,这时候也是由于线程推进顺序的影响,可能会有2000 b=1000和b=1000 1000这两种结果。
      

  4.   

    补充一句:第一种情况也可能打印出2000 b=1000。总而言之,打印出1000 b=1000, 2000 b=1000, b=1000 1000这三种结果都是正确的。
      

  5.   

    第二种情况么有2000 b=1000,只可能有b=1000 2000.总而言之是1000 b=1000, 2000 b=1000, b=1000 1000,b=1000 2000四种结果。