文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

聊聊Synchronized的优化

2024-12-03 13:45

关注

 早期版本synchronized性能较低的原因

在早期版本中,synchronized是一种重量级锁,其底层由Monitor实现,而Monitor又依赖于操作系统的Mutex Lock。线程获取到锁后,需要切换状态,而操作系统在实现线程的切换时,需要从用户态转为核心态,这是一个非常耗时,非常重的操作。因此在之前,synchronized是一种重量级锁。

JDK1.6之后对synchronized的优化

现在的synchronized已经没有之前那么笨重了,在虚拟机层面,对synchronized做了较大的优化,引入了自旋锁、适应性自旋锁、锁消除、锁粗化,可以减少锁操作的开销。

自旋锁

有时候,获取到锁的线程执行的操作耗时极短,为了这么点微不足道的时间,将接下来等待锁的线程挂起非常的不值得。挂起线程的操作需要在核心态完成,从用户态切换到核心态,耗时比较严重。

因此现在增加这么一样操作,让等待锁的线程执行忙循环等待,不停地去尝试获取锁,像一种自旋的操作,故称之为自旋锁。

如果之前线程占有锁的时间极短,那么自旋锁的性能将非常的好。但若是占有锁的时间较长,那么自旋锁将白白消耗CPU的资源,在自旋次数到了之后,将会被挂起。

在jdk1.4的时候,自旋锁默认关闭;jdk1.6之后,自旋锁默认开启,默认自旋10次,当然也可以使用PreBlockSpin来修改自旋次数。

自旋锁的痛点在于:无法在不同场景中,确定出一个可靠的自旋次数。因此,衍生出来适应性自旋锁。

适应性自旋锁

在适应性自旋锁中,自旋的次数不再固定,一般由之前自旋的次数和锁持有者的状态决定。

如果在一个锁对象上,之前的线程都能通过自旋来获取到锁,并且没有超过自旋次数,那么虚拟机认为,通过自旋获取到锁的概率很大,下一次会增加自旋的次数。相反的,如果之前很少有线程通过自旋获取到锁,那么虚拟机会减少自旋的次数,减少到一定次数后,甚至会直接放弃自旋,升级为重量级锁。

可以看出,适应性自旋锁十分机智。

锁消除

从字面意思上可以看出,这是一种直接去除锁的方法,简单粗暴。

对于那些根本不可能存在锁竞争却又包含锁的情况,虚拟机会直接消除这个锁,避免无意义的锁请求。比如我在纯单线程中对某个方法或者变量加锁,或者调用内部实现有锁的对象(Vector、StringBuffer与HashTable等),虚拟机会直接消除毫无意义的加锁。

锁粗化

在上一文中【多线程】浅说Synchronized,我们谈到了synchronized的应用-双重检验锁的优化过程,强调将加锁的范围尽量限制得小一些,直到存在锁竞争的实际区域才加锁,这样程序运行更加高效。

但是,如果存在这样的一种情况:反复的对同一个对象执行加锁解锁的操作,也会导致CPU资源的过度消耗。

锁粗化,就是将反复的加锁操作粗化成一个范围更大的锁,这样加锁只有一次。

例如,在循环内部,调用StringBuffer的append操作(关于StringBuffer,可以参考我的另外一篇文章【JAVA】String、StringBuilder、StringBuffer三者的区别),每次append都需要加锁,虚拟机检测到这种情况后,首先会对append脱锁,然后进行锁粗化,将锁的范围扩大到循环外部。

锁的状态

锁的状态有以下几种:

  1. 无锁状态
  2. 偏向锁状态
  3. 轻量级锁状态
  4. 重量级锁状态

其中,无锁状态对应于锁消除,Monitor对应于重量级锁,也就是1.6之前的synchronized。

偏向锁

偏向锁的核心要义就体现在“偏”字上,这个锁偏向第一个获取到它的线程。

在大部分情况下,不存在激烈的锁竞争,总是由同一个线程获取到该锁。那么为了减少同一个线程获取锁带来的开销,就引入了偏向锁。

如果一个线程不断的获取到了锁,那么该锁就进入偏向锁状态。当这个线程再次请求锁时,无需做任何同步操作,直接获取到锁。

当然,偏向锁适用于基本无锁竞争的情况,当锁竞争激烈时,偏向锁就失去了作用,会升级为轻量级锁。

轻量级锁

在偏向锁的状态下,此时又出现了一个线程,与偏向线程竞争该锁,此时该锁会升级为轻量级锁。

举个例子,比如创建一个线程1执行同步print()方法打印奇数,这时候的锁状态为偏向锁。此时,再创建一个线程2同样执行同步print()方法打印偶数,偏向锁就会升级为轻量级锁。线程1打印某个奇数时,线程2并没有被挂起,而是处于一种自旋状态,这种自旋效率很高。可是,当我再创建100个线程时,同样执行同步print()方法,自旋的效率将会变得十分低下,此时轻量级锁会升级为重量级锁,即使用Monitor来进行同步。

锁的升级

无锁、偏向锁、轻量级锁与重量级锁,会随着锁竞争的升级而升级。

从一开始的偏向锁,产生锁竞争后,升级为轻量级锁,自旋失败后,升级为重量级锁,一般来说,锁的升级是单向的。

 

来源:今日头条内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯