JDK1.6对synchronized的优化

一、锁消除

这个优化是由JIT来实现的,如果你的方法内,没有涉及到那些临界资源的使用,那么JIT会将synchronized去掉。

我们用代码来举个例子。

public synchronized void method(){
    Person p = new Person();
    p.age = 18;
}

上面这段代码,被JIT优化后,会把synchronized去掉,注意,是经过JIT编译后才会去掉!!

原始代码依旧是保留synchronized的。

public void method(){
    Person p = new Person(); // 每个线程进来都new一个新的对象,整个方法的操作是安全的,加不加锁都一样
    p.age = 18;
}

二、锁范围调整

这个也是JIT来做的优化,他会在不影响代码正常业务的情况下,把锁住的代码范围提高。

我们依旧拿代码举例子

此方法中,synchronized的粒度过小了,并且没有什么需要在循环中争抢的资源,可以考虑优化

public void method(){
    for(int i = 0; i < 999; i++){
        synchronized(this){
          // 业务代码
        }
    }
}

那么优化后的结果如下,相当于我一进来就把锁拿了,然后再执行循环,这样就只有1次加锁和解锁操作。

public void method(){
    synchronized(this){
        for(int i = 0; i < 999; i++){
            // 业务代码...        
        }
    }
}

三、锁升级

原来的synchronized是纯重量级锁,就是一上来,先抢锁,没抢到的全部挂起等待(用户态和内核态切换,开销大)

于是,JDK1.6就进行了优化。

首先一上来,他是一个无锁的状态,当有线程获得锁了,那么升级为偏向锁,偏向锁也还没有真正的上锁,他在对象头上,记录持有线程的ID,然后下次过来,先比较ID,如果是同一个线程ID,则直接放行,这个过程没有上锁解锁操作。

如果现在另外一个线程进入了,那么就升级为CAS机制的锁资源争抢,就是线程A获取到资源了,那么线程B使用CAS自旋的方式不断的尝试获取锁。如果长时间获取不到,或者后面又来了C、D、E、F...等多个线程同时争抢,那么最终就会升级到重量级锁。

重量级锁就会涉及到用户态和内核态的一个切换,但是也比大量的CAS要好一些。

所以注意了,并不是任何时候CAS争抢都要比重量级锁好的,CAS自旋的时候,消耗了CPU资源,但是大部分时间其实是空转的一个情况,因为你抢不到锁,10个线程同时争抢,只有1个线程抢成功,其他9个就必须自旋。

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值