Java synchronized简析

前言

在Java并发编程里synchronized关键字一直都有着重要的地位,在Java中任何对象都可以作为锁对象,对于普通的方法锁定的是当前实例对象,对于静态方法锁定的是当前的类对象,对于同步代码块锁定的是括号里的对象。最开始synchronized的实现是采用底层操作系统的互斥锁实现,这种锁需要在内核和用户态之间切换效率非常的低,不过在1.6版本引入了大量的优化,使得synchronized的效率有了很大的提高,现在就来总结一下synchronized锁实现的机制。

JDK优化

JDK的优化主要包含锁粗化、锁消除、偏向锁、轻量级锁和自适应自旋锁,下面通过简单地说明这些锁优化具体做了什么。

private String getString() {
    StringBuffer stringBuffer = new StringBuffer();
    for (int i = 0; i < 10; i++) {
        stringBuffer.append(i);
    }
    return stringBuffer.toString();
}

上面的代码实现了向StringBuffer对象中添加多个不同的数字,我们知道StringBuffer是线程安全的类实现,它的每个方法都会在使用之前加锁,实际上完全没有必要每一步都请求锁,只要在循环的外面添加一个锁,里面的每一步就不必在申请锁,这种优化就是锁粗化,减少多个不必要紧密连接在一起的锁,将多个连续锁扩展成一个范围更大的锁。

如果再仔细的查看上面的源码会发现StringBuffer对象仅仅是一个本地变量,不管它在哪个线程中调用由于对象始终只处于这个线程的调用栈中并不会和其他线程共享这个变量,完全没有必要加上锁操作,最终执行代码就会去掉这个synchronized锁,这就是锁消除优化。

偏向锁

偏向锁的引入者发现大多数情况下锁不仅不存在多线程竞争,而且总是由同一个线程获得,偏向锁能够有效的降低获取锁的代价。Java的对象在头部有一个Mark Word字段,偏向锁的数据就记录在其中。

这里写图片描述

获取锁:检测当前对象MarkWord是否设置为当前线程偏向锁,是继续执行代码,否则测试Mark Word中偏向锁是否设置如果没有设置使用CAS竞争锁,如果设置了就使用CAS将对象头里的偏向锁指向当前线程。

撤销锁:只有当其他线程竞争锁的时候才会出现释放锁,撤销的时候在没有正在执行的字节码的时候首先测试拥有该偏向锁的线程是否处于活动状态,如果是就让锁偏向于其他线程或者设置锁不适合作为偏向锁,如果没有活动就清空偏向锁数据。如果被判定不适合做偏向锁就会发生琐升级,使用轻量级锁来做同步操作。

轻量级锁

轻量级锁基于如下假设:在真实的情况下程序中大部分同步代码都处于单线程运行,也就是无锁竞争状态,这时应该避免使用操作系统层面的重量级互斥锁,而是使用CAS完成锁的获取和释放操作。当锁存在竞争的情况下,执行CAS失败的线程会继续做自旋操作,尽量不进入操作操作系统的底层锁。如果CAS失败多次才会调用操作系统的底层锁进入阻塞状态。

变量名 作用
Owner 初始为null,当有线程获取当前锁对象,内容为线程的标识,琐释放后为null
EntryQ 关联操作系统的互斥锁,阻塞所有无法获取当前锁的线程
RfThis 阻塞在重量级锁上的线程个数
Nest 用来计数重入锁的计数
HashCode 保存从Mark Word拷贝过来的对象HashCode
Candidate 为避免多个线程同时竞争同一个锁,引起不必要的上下文切换消耗性能;如果为1代表只唤醒下一个线程,否则就唤醒所有等待线程

获取锁:首先测试对象是否已经和MonitorRecord关联,如果没有关联需要做膨胀处理,也就是使用对象数据初始化MonitorRecord就是把MonitorRecord的Owner字段设置为当前线程标识,然后将MonitorRecord的地址使用CAS设置到对象头的LockWord,如果设置成功获取轻量级锁成功;如果获取失败说明有其他线程也再做获取锁操作,之后需要使用之前线程膨胀的MonitorRecord的owner和当前线程标识做CAS,如果成功表明获取锁成功,否则需要继续自旋操作;如果多次自旋依然无法获取锁,这时就升级锁到重量级锁也就是操作系统互斥锁,在该锁上做阻塞等待。

释放锁:首先检查对象是否膨胀并且线程是锁的拥有者,不是则抛出异常,如果RecordMonitor的nest属性大于1需要减去1,如果等于1需要检查rfThis属性查看是否有线程在操作系统互斥锁上等待获取锁,如果不为0就唤醒等待线程,否则就缩小一个对象并且将对象头部记录的LockWord和之前的hashcode换回来,接触RecordMonitor和对象的关系。

猜你喜欢

转载自blog.csdn.net/xingzhong128/article/details/80559356