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);
  }
 }
 
 输出结果是
 1000
 b = 1000
 
 问题一:t.start()执行后另一个线程开始进行,同时主线程也在进行,
 我不明白如果两者从这里开始“同时”进行,为什么不是由CPU自由分配哪一个线程先进行一点点,从而将m1()或m2()先锁定,执行完之后再执行另一个,而是确定地先执行m2(),输出不含“b = ”的那一行结果,然后才进行m1()
 
 问题二:我在m2()的b = 2000;后加上System.out.println("b = " + b);
 输出结果变成了
 b = 2000
 2000
 b = 1000
 为什么连main()函数最后的输出也改变了?
 
 希望高手能帮我讲解一下这个程序详细的运行顺序,谢谢!

解决方案 »

  1.   

    首先,你这里m1()和m2()都定义成synchronized,那么不管哪个线程先执行其中一个就获得了锁,别的线程只能等待,这里非主线程先执行,那么主线程只能等到非主线程的m2()执行完,才能开始执行m1()。m2先执行完将b赋值为2000,此时主线程开始执行,同时System.out.println(tt.b);也执行,如果主线程对b的赋值快就会首先输出1000,如果System.out.println(tt.b);执行早就输出2000。
    所以System.out.println(tt.b);有可能是1000或是2000;public synchronized void m1() throws Exception{
      Thread.sleep(2000);
      b = 1000;
    这样的话肯定System.out.println(tt.b);先执行,总会输出2000
      

  2.   

    我今天也刚好看到这个视频,虽然是t.start();再tt.m2();,事实上系统是先锁定M2执行完之后才锁定M1的,你可以在改成t.start();Thread.sleep(1000);tt.m2();就可以保证先锁M1再锁M2
      

  3.   


    我主要就是不理解为什么先锁那一个是可以这样确定的
    视频里面说锁定的是方法里面的语句,一旦方法得到锁其他的方法就不能再运行这个被锁的方法里面的语句了,难道是因为m1m2其中之一先执行了sleep()然后锁定方法,导致另一方无法使用sleep()从而不能同时进行?不知道理解的对不对
      

  4.   


    m1和m2同时加了synchronized,加入线程1先执行m1或者m2,那么线程2此时不能执行m1和m2,但是他可以执行未被synchronized修饰的方法,只有等线程1执行完,线程2才能执行被synchronized修饰的方法
      

  5.   


    还是非主线程先被锁,m1()先执行是吗?但是为什么会先执行main()最后的那个输出?能不能详细解释一下各条语句执行的顺序?
      

  6.   


    先执行的是m2,之后可能是m1或者System.out.println(tt.b)先执行,最后是m1
      

  7.   

    或者这么说显示m2,之后可能是m1中的b = 1000;或者System.out.println(tt.b),此时m1开始sleep,最后m1执行完