t.start();然后调用 run(),执行m1();由于该方法是synchronized同步方法,所以t线程将拥有对象tt的内部锁,此时如果该内部锁不被释放(m1方法执行完),tt.m2();方法是不能被执行(同步方法的限制)。然后其中,sleep方法只是计时等待,并不会释放所持有的锁,故线程t一直拥有着tt对象的内部锁(即使调用了5秒sleep),直到方法执行完(执行期间就system.out输出b了,b=1000),然后主线程才执行m2方法。这块楼主要明白,
1.synchronized方法的原理和使用,一旦一个线程执行了一个对象的同步方法,其他线程是不能再执行该对象的所有同步方法的。
2.sleep方法只是进入计时等待,并不释放锁,时间一到就继续执行下去。而想要释放锁,就要用wait方法。

解决方案 »

  1.   

    楼主可以用debug工具自己查看详细的执行过程,下面是我测试的代码以及结果,黑色部分是添加的辅助说明代码:
    public class TT implements Runnable  {
          int b = 100;
          
          public synchronized void m1()  throws Exception {
           System.out.println("执行m1()方法 " );
           b = 1000;
              Thread.sleep(5000);
              System.out.println("b = " + b);
          }
          
          public synchronized void m2() throws Exception {
           System.out.println("执行m2()方法 " );
           Thread.sleep(2500);
              b = 2000; 
              System.out.println("b = " + b);
          }      public void run() {
            System.out.println("执行run()方法 " );
              try {
                  m1();
              } catch(Exception e) { e.printStackTrace(); }
          }
    public static void main(String args[]) {
          TT tt = new TT();
          Thread t = new Thread(tt);
          t.start();
          try{
          tt.m2();}
          catch(Exception e){
           e.printStackTrace();
          }
    }
    }程序的执行过程如下:
    执行m2()方法 
    执行run()方法 
    b = 2000
    执行m1()方法 
    b = 1000分析:
    由此可见程序首先执行的是m2()方法,然后是run()方法,最后是m1()方法。所以当执行 tt.m2();时,内部的实际过程是先执行了调用的方法,其次才执行线程的run()方法,而在run()方法中又调用执行了m1()方法
      

  2.   

    这里的m2()和m1()方法都加了锁,t线程开始执行,也就是调用了m1()方法,而m1()方法是加锁的,将b的值改变为1000,然后睡眠,再次过程中执行m2()方法,但是m2()同样是加锁的方法,所以必须等待m1()这方法释放锁之后才去执行,因为输出语句在m1()方法里面,所以会输出1000。如果你将m2()方法的锁去掉,则执行m2()的时候不受m1()的限制,将会输出2000。你再多看几遍视频,就能明白了。
      

  3.   

    原始的代码挺恶心的,因为只要有输出,就必定是b=1000。
    实际上,m1,m2是各自独立的动作,用锁回避了并发冲突。
    只是谁先谁后其实是不确定的,楼主可以在m2当中加上打印。
    然后在main当中,每5秒钟循环做一次原main的动作,就会知道了:主线程和子线程谁先被执行是不确定的。
      

  4.   

    用synchronized修饰方法时,等价于从方法第一行到最后一行 对当前对象加锁public synchronized void add(Object obj){
    1;
    2;
    }等价于如下形式:public void add(Object obj){
    synchronized(this){
    1;
    2;
    }
    }因此,假如你的m1方法拿到当前对象的锁标记后执行赋值并sleep(继续持有锁标记),此时m2方法也需要当前对象的锁标记,但是拿不到,因此不会造成并发冲突。
    这里还有个问题,如4楼所说,主线程 和 t线程的执行顺序是不确定的,只是t线程先拿到时间片抢先执行的可能性更大
      

  5.   

    补充一句,如果楼主认为m2方法的synchronized修饰无关紧要,那就试试不加,看看结果
      

  6.   

    sleep会暂停 但不会释放锁,
    wait会释放锁知道被 notufy楼主应该是这两个概念没弄清楚吧http://blog.csdn.net/liyantianmin/article/category/2735267
    可以看看
      

  7.   

    sleep不释放锁 ~~~当然是输出1000啊 直到m1方法执行完了才释放对象锁给m2方法 而m2方法没有输出语句~~所以楼主的程序运行结果就是1000
      

  8.   

    线程调用完全是随机的,m1()中打印的b有可能是m1()方法赋的值,也可能是m2()方法赋的值.