【多线程】Synchronized的优化

对synchronized不太了解的同学,可以先参考我的另外一篇文章【多线程】浅说Synchronized

早期版本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来进行同步。


锁的升级

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

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

全部评论
更多文章请移步https://blog.csdn.net/qq_33591903
点赞
送花
回复
分享
发布于 2020-04-22 09:19

相关推荐

#简历#先说一说我自己的想法,很多人都很排斥苍穹外卖,认为没什么技术点和含金量,但实际上我觉得恰恰相反,苍穹外卖虽然代码本身并不是你自身能力的证明,但是是作为一个新人学习时很好的跳板和原始框架,在这个框架上进行的改进可以很好的辐射到你自己的个人成果上,并作为你和面试官聊天的筹码大多数人的苍穹外卖只写增删改查,千篇一律,吸引不了面试官,所以这才让大家误以为只要是苍穹外卖就不要写进简历里这种误区,但实际上如果你在原有的层面上进行改进,并作为你的项目亮点和面试官介绍,告诉他你的苍穹外卖和别人的有什么不同,增加了哪些技术难点,这才显得你是完全自己理解了这个项目,并且有自己动手实践项目的能力,而不是就看了个课程就以为自己会了,就当成自己的了,如此一来,这反而成为你的加分项苍穹外卖为什么看的人最多,说明它好啊,如果它不好,为什么看的人还这么多,想清楚这个逻辑,我觉得要做的最重要的事,就是如何在原有框架上进行改进提效,比起听其他人的话重新搞一个项目性价比高得多,而且我亲测项目并没有成为我找到工作的阻碍,我投的大厂一大半都给我面试了,而且很多不止一个部门,退一万步说,当你手头没有其他项目的时候,有苍穹外卖总比什么都没有的好很多,不需要因为苍穹外卖有任何心理负担关于简历的任何部分都欢迎大家提意见,十分感谢大家,祝大家找实习+秋招顺利上岸,offer拿到手软#简历中的项目经历要怎么写##我的上岸简历长这样##最后再改一次简历##简历##简历被挂麻了,求建议#
点赞 评论 收藏
转发
点赞 收藏 评论
分享
牛客网
牛客企业服务