public class TT implements Runnable {
int b = 100;

public synchronized void m1() throws Exception{
//Thread.sleep(2000);
b = 1000;
Thread.sleep(5000);
System.out.println("b = " + b);
}

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

public void run() {
try {
m1();
} catch(Exception e) {
e.printStackTrace();
}
}

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.   

    我在eclipse下面执行的结果,当我正常整形的时候结果是:
    1000
    b = 1000
    当我设立了一个断点后的执行结果为:
    b = 1000
    2000
    为什么会是这个样子的呀?请教各位高手啊!
      

  2.   

    synchronized 加了也不是你想像的那个同步!
    断点监视启动了另一个线程,而且不止一个!
      

  3.   

    你拥有两个线程,
    一个是你创建的线程
    一个是当前的主线程
    如果你在主线程里边设置断点当前的主线程当然不会再执行,你创建的线程会继续执行。
    在这里应该实现了你的同步,因为你创建了一个对象tt,调用的也是同步方法。
    只不过:
            tt.m2();
    执行完毕的时候释放了对象锁,你新创建的线程得以执行
    赋值表1000
    然后又执行
    System.out.println(tt.b);
    最后又输出
     System.out.println("b = " + b);
      

  4.   

    更奇怪的是我再 m2()中加了 System.out.println("b = = "+b);
    结果竟然是 b = = 2000
              2000
              b = 1000
      

  5.   

    我不知道楼主说的正常情况,是不是每次都是一样的。
    谈一下我的个人理解:
      首先,主函数中的System.out.println()方法,显示的内容tt.b是没有同步锁的。
      其次,解释第一种现象。
         1.主函数运行t.start()方法,会让创建的线程进入runnable状态,等到t获得CPU时间片时运行run方法。
            但是,t还没有获得CPU的时间片,因为,CPU在被主线程执行,且主线程的时间片还没有被用完。
         2.调用tt.m2()方法,主线程sleep(2500);
         3.由于主线程sleep,t线程获得运行机会,调用m1();方法,但是由于m1是线程同步的,所以,t线程被同步阻塞。
         4.主线程sleep结束,将tt.b赋值为2000 。tt.m2();方法结束。(互斥锁被释放)
         5.t线程由于互斥资源被释放,进而执行m1中的代码。将tt.b赋值为1000 。
         6.主线程执行System.out.println(tt.b);方法。
         7.t线程进行sleep,继续后面的代码。
         问题的关键是,5和6的执行顺序,并不是固定的。有可能先进行6然后才是5,多线程并发嘛,要根据操作系统的当前状况而定。
         但是,楼主的系统,可能是先5后6 吧。
      第三,解释第二种现象。
         1.设置断点的情况下,被设置断点的线程会在断点进行挂起。
         2.主函数运行t.start()方法后,会让创建的线程进入runnable状态,由于主线程被断点挂起,所以,t会得到CPU的时间片而执行run方法。
         3.然后调用t.m1()方法。(这是即使手快,让断点在m1的sleep结束前,主线程就执行到tt.m2()方法,也不行,因为tt.m1()是线程同步的,
          并且,还没有执行完毕,这时,你会发现程序会等一会,才执行tt.m2()。)
         4.主线程调用tt.m2()方法。
         5.断点调试的结果,一般都是不会变化的,因为,人的反映还是没有计算机快的。
          呵呵。
      

  6.   

    我觉得楼上的解释有问题,那两个方法不都用了synchronized吗?那么只有等该方法结束了另一个线程才能得到时间片,即使它sleep(),也要等它运行结束
      

  7.   


    main线程中调用System.out.println(tt.b)是不用等待m1方法结束才运行的。在同一类实例中,所有被synchronized修饰的方法才需要等待同步锁。