深入探析Java线程锁机制

      今天在iteye上提了一个关于++操作和线程安全的问题,一位朋友的回答一言点醒梦中人,至此我对Java线程锁有了更加深刻的认识。在这里也做个总结供大家参考。

      先看几段代码吧!

   代码一:

public class TestMultiThread2 implements Runnable{

	private static Object o = new Object();
	
	private static Integer si = 0;
	
	private static AtomicInteger flag = new AtomicInteger();
	
	@Override
	public void run() {
		for(int k=0;k<2000000;k++){
			synchronized(si){
				si++;
			}
		}
		flag.incrementAndGet();
	}
	public static void main(String[] args) throws InterruptedException{
		TestMultiThread2 t1 = new TestMultiThread2();
		TestMultiThread2 t2 = new TestMultiThread2();
		ExecutorService exec1 = Executors.newCachedThreadPool();
		ExecutorService exec2 = Executors.newCachedThreadPool();
		exec1.execute(t1);
		exec2.execute(t2);
		while(true){
			if(flag.intValue()==2){
				System.out.println("si>>>>>"+si);	
				break;
			}
			Thread.sleep(50);
		}

		
	}	
	
}

   为了方便看,重复的就不插入了,从代码二到代码四只插入run()方法中的代码,其他地方都一样

  代码二:

    public void run() {  
        for(int k=0;k<2000000;k++){  
            synchronized(o){  
                si++;  
            }  
        }  
        flag.incrementAndGet();  
    }  

  代码三:

    public void run() {  
        for(int k=0;k<2000000;k++){  
            synchronized(o){  
                si++;  
                o = new Object();  
            }  
        }  
        flag.incrementAndGet();  
    }  

    代码四: 

   public void run() {  
        for(int k=0;k<2000000;k++){  
            synchronized(o){  
                si++;  
                Object temp = o;  
                o = new Object();  
                o = temp;  
            }  
        }  
        flag.incrementAndGet();  
    }  

  有了这四段代码我想问题大概可以说明白了,这里说一下输出吧。

 

  代码一:<4000000

  代码二:=4000000

  代码三:<4000000

  代码四:<4000000(PS:这个结果非常接近4000000)

 

      这里说明一下我测试中碰到的问题,代码四一直没有跑出我想要的结果,主要是开始我设的循环次数太少,其实这里如果要这个现象更加明显一些可以在中间多new 几个Object 如下面的代码五,这样现象就比较明显了.

  代码五:

    public void run() {  
        for(int k=0;k<2000000;k++){  
            synchronized(o){  
                si++;  
                Object temp = o;  
                for(int m=0;m<10;m++){  
                    o = new Object();  
                }  
                o = temp;  
            }  
        }  
        flag.incrementAndGet();  
    }  

 为什么会出现上面的现象:

     代码一:当si做++操作后(可以直接看字节码,这里不贴了),在putstatic之前有几步操作,就是我们常说的非原子操作,而这时候si已经不是原来的对象了,这样锁对另外一个线程来说就失效了,我想代码三和代码四就是最好的佐证,代码四更有说服力。当时因为没有出现预想的情况困惑了挺久。

    其实这里用字节码来解释还不是很严谨,最好的当然直接是汇编代码

    如有什么问题还希望各位读者指正。

 

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值