偏向锁,轻量级锁,自旋锁和重量级锁

jdk1.6之前,synchronized实现是在线程状态“运行”-“阻塞”-“运行”之间切换
jdk1.6之后,因为线程状态间的切换低效,所以对synchronized实现同步功能进行了优化,引入偏向锁,轻量级锁,自旋锁和重量级锁等概念,来提高synchronized实现同步锁的效率。
synchronized获取不到锁之后,不会立即阻塞线程。随着锁竞争不断激烈,JVM处理锁的方案也不断升级,按照偏向锁,轻量级锁,自旋锁和重量级锁的顺序升级,资源消耗递增,效率递减
在介绍各个锁之前,先介绍几个相关概念

1.对象头和MarkWord

java的对象由三部分组成:对象头,实例数据,填充字节(对象占用内存是8bit的倍数,不足的需要填充)。
非数组对象的对象头由两部分组成:指向类的指针和Mark Word。
数组对象的对象头由三部分组成,比非数组对象多了块用于记录数组长度。
Mark Word用于记录对象的HashCode和锁信息等,在32位JVM中的Mark Word长度为32bit,
在64位JVM中的Mark Word长度为64bit。
Mark Word的最后2bit是锁标志位,代表当前对象处于哪种锁状态,当Mark Word处于不同的锁状态时,Mark Word记录的信息也有所不同

![32位的JVM中,不同的锁状态对应的MarkWord记录的信息](https://img-blog.csdnimg.cn/20190426111749552.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L21lbmdrZXkxOTkw,size_16,color_FFFFFF,t_70)

无锁和偏向锁的锁标志位都是01,只是在前面的1bit区分了这是无锁状态还是偏向锁状态。

随着锁的升级,Mark Word里面的数据就会按照上表不断变化,JVM也会按照Mark Word里面的信息来判断对象锁处于什么状态

以下都以对象F作为同步锁

1.偏向锁

线程A请求对象F获取锁时,此时,F还没有被锁定过,锁标志为无锁状态,是否偏向状态为否,此时,A线程获取到锁,锁状态设置为偏向锁,是否偏向状态设置为是,并在Mark Word中设置线程A的ID,表示
线程A获取到偏向锁,存线程A的ID的意义在于,线程A再次请求锁时,检测到MarkWord中已经存在相同的ID,表示A已经获得了偏向锁,直接执行同步代码即可,偏向的意义就在此体现,如果获取失败,进行下一步

2.轻量级锁

线程B请求锁时,发现同步锁处于偏向状态,CAS获取锁,获取成功,将MarkWord中的线程ID替换为线程B的ID;获取失败,则撤销线程A的偏向锁,表示当前有一定的竞争,升级为轻量级锁,过程如下:
在线程B的栈中开辟一片空间P,操作一,保存指向MarkWord的指针;操作二,MarkWord中保存指向空间P的指针,如果上述两个操作都成功,表示线程B获取锁成功,MarkWord中的锁状态设置为轻量级锁
如果获取锁失败,进行下一步

3.自旋锁

自旋锁只是一种不断尝试获取轻量级锁的过程。如果重试一定次数后获取到锁,就执行同步代码,否则进行下一步

4.重量级锁

自旋锁重试之后如果抢锁依然失败,同步锁会升级至重量级锁,重量级锁就是java最原始的同步锁,在这个状态下,未抢到锁的线程都会被阻塞,等待被激活。

以上是JVM提高锁效率的方式在应用层,我们也可以采取一定的措施来提高锁效率

1,减少锁的持有时间
不需要同步执行的代码,不要放在同步代码块中。同步块中代码减少,锁的持续时间短,锁的性能会有所提高。

2,减小锁粒度
把资源分批使用不同的锁,不同批次的资源的操作互不影响。
比如ConturrentHashMap类,把map分成多段,每段一个锁,不在一段的数据可以同时修改。

3,锁分离
把关系不大的操作使用不同的锁,使这些操作互不影响。
比如LinkedBlockingQueue类,从队列头获取数据的take()方法和从队列末尾添加数据的put()方法分别使用不同的锁,两者互不影响。

4,锁粗化
指的是当虚拟机需要连续对同一把锁进行加锁和释放时,尽量改成只使用一次锁。
比如连续多个synchronized语句块,或循环中的synchronized语句块,用的是同一个对象作为锁,可以直接用一个synchronized语句块把他们都包含起来。

5,弃用synchronized关键字
不使用synchronized关键字,可以自己编写代码实现类似偏向锁、自旋锁的功能,减少因为同步锁而带来的效率损耗。比如自己实现的自旋锁。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值