从java一道多线程题目想到

一道 java多线程题目,请思考下输出是什么?

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 stub
		ThreadTest tt=new ThreadTest();
		Thread t=new Thread (tt);
		t.start();
		//Thread.sleep(10);
		tt.m2();
		System.out.println("MAIN,now b="+tt.b);
	}

}


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

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 stub
		ThreadTest 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.
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值