先上代码:
public class TT implements Runnable {
int b = 100;
public synchronized void m1() throws Exception {
System.out.println("m1() starts...");
b = 1000;
Thread.sleep(2000);
System.out.println("m1(): b = " + b);
System.out.println("m1() ends...");
}
public synchronized void m2() throws Exception {
System.out.println("m2() starts...");
Thread.sleep(1000);
b = 2000;
System.out.println("m2(): b = " + b);
System.out.println("m2() ends...");
}
public void run() {
try {
m1();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String args[]) throws Exception {
System.out.println("main() starts...");
TT tt = new TT();
Thread t = new Thread(tt);
t.start();
tt.m2();//方法调用,顺序执行,主线程休眠1秒钟
System.out.println("main(): b = " + tt.b);
System.out.println("main() ends...");
}
}
这段代码是从马士兵老师所录制的视频:“11_线程同步_7_生产者消费者问题”中摘取出来的。
本人稍加改进,以便分析。
这段程序有趣的是,它会有两种不同的输出结果:
输出1:
---------- java ----------
main() starts...
m2() starts...
m2(): b = 2000
m2() ends...
main(): b = 2000
main() ends...
m1() starts...
m1(): b = 1000
m1() ends...
输出2:
---------- java ----------
main() starts...
m2() starts...
m2(): b = 2000
m2() ends...
m1() starts...
main(): b = 1000
main() ends...
m1(): b = 1000
m1() ends...
分析:
当程序执行到t.start()语句时,会分出两条执行路径:
①线程t将会被启动,然后JVM会去调用线程对象tt的run()方法;
②main()线程继续执行到tt.m2()语句,调用方法m2()。
显而易见,路径②的执行速度快于路径①的执行速度,所以,一定是同步方法m2()先执行。
由于synchronized关键字的作用,m2()一旦开始执行,m1()就无法开始执行,只能等待m2()方法结束,而m2()是在main()线程里的方法调用,所以main()线程休眠1秒钟。
而为什么会有两种不同的输出结果呢?
其实原因很简单:就是要看m2()线程执行完毕之后,main()线程和t线程谁能抢占到CPU的资源,谁能先获得CPU的调度从而先执行:
如果是main()线程能先执行,则结果为:输出1;
如果是t线程能先执行,则结果为:输出2。
我在这里就不做出过于详细的分析了,有兴趣的可以去观看马士兵老师的JavaSE的视频。
有疑问的欢迎留言,如果本人哪些地方有说错的,还请多多指正!谢谢!
main()线程:JVM分配给main()方法的线程