从java一道多线程题目想到

来源:互联网 发布:公司注销,淘宝企业店铺 编辑:程序博客网 时间:2024/06/03 16:22
一道 java多线程题目,请思考下输出是什么?


=======================================
输出结果是:

m2:b=2000

MAIN,now b=2000

m1:b=1000


程序中两个函数都用到了synchronized同步,我们知道同步锁住的是对象,也就是tt。当一个线程拿到了tt的锁后,其他的线程就被cpu安排到等待队列(阻塞)中。

我们分析下程序执行过程:

程序开始后,main()线程先开始运行,直到t.start(),另起了一条新线程t, t调用run函数。

多线程是并行的,t.start()并不影响main()线程的继续走下去。这时main()调用了m2()函数,很快m2抢到了tt的锁,并改写了b的值,输出了m2:b=2000.

m1()也加了synchronized, 为什么它没抢到?因为它慢了一步。。。。线程t需要调用run,run再调用m1,它没有main()直接调用m2快。

接下来m2() 运行完以后,CPU去看就绪队列中是否有线程在等待,发现m1,于是就把锁给了m1

但是main()最后面的输出流不需要抢锁,直接read内存中共享的变量b值输出即可。

那么,m1能不能先抢到锁呢?可以,我在测试中发现,极个别也会让m1先抢到锁,继而m1先输出,然后m2,然后system.out.println。

这是一种情况,为了验证,我们再main()函数调用m2()之前,让主线程sleep一下下,就让它睡1ns好了。

public class ThreadTest implements Runnable {int b=100;public synchronized void m1() throws Exception{b=1000;System.out.println("m1:b="+b);}public synchronized void m2()throws Exception{//Thread.sleep(2500); b=2000;System.out.println("m2:b="+b);}public void run(){try{m1();}catch(Exception e){e.printStackTrace();}}public static void main(String[] args) throws Exception {// TODO Auto-generated method stubThreadTest tt=new ThreadTest();Thread t=new Thread (tt);t.start();Thread.sleep(0, 1);;tt.m2();System.out.println("MAIN,now b="+tt.b);}}
这个时候发现,输出的结果基本上是

m1:b=1000

m2:b=2000

MAIN,now b=2000



道理可能大家都明白了,就是因为sleep延迟了1ns的原因,本来m2可以很轻松抢到锁的,现在让m1轻松先抢到了实例tt的锁,首先锁定了。

值得强调的是,synchronized 同步的是对象,变量是仍然可以访问的。


注意上面代码在不同的计算机上结果可能是不一样的,我的电脑配置 2.6GHz主频,内存8G.
0 0
原创粉丝点击