目录
一、synchronized的优化机制
1)无锁状态
2)偏向锁状态:非必要,不加锁
3)轻量级锁
4)重量级锁:挂起等待
二、锁消除
三、锁粗化
锁的粒度
锁粗化的好处
在这一篇文章当中,我们也提到了synchronized的作用。
Java对于synchronized的初步认识_革凡成圣211的博客-CSDN博客synchronized,死锁,https://blog.csdn.net/weixin_56738054/article/details/128062475?spm=1001.2014.3001.5501 回顾一下,在synchronized当中,两个线程如果针对同一个对象加锁,如果一个线程可以获取到锁,另外一个线程就会进入阻塞等待的状态。
关于synchronized锁的一些特性,在这一篇文章当中,已经提到了。
【JavaEE进阶】锁的特性_革凡成圣211的博客-CSDN博客Java锁的特性https://blog.csdn.net/weixin_56738054/article/details/128574608?spm=1001.2014.3001.5501
下面,再回顾一下synchronized的几个特性:
特性一、synchronized是一个非公平锁;
特性二、synchronized是一个可重入锁;
特性三、synchronized是一个悲观锁;
特性四、synchronized是一个互斥锁,两个线程不可以同时占有一把锁;
特性五、synchronized可以由一个轻量级锁转化为重量级锁。
一、synchronized的优化机制
以下四个过程:就是在线程进入synchronized代码块当中之后,加锁的过程,就可能会经历下面这几个阶段。
synchronized(locker){
//在这个内部,进行加锁的过程
}
synchronized内部其实还有一些优化机制,存在的目的就是为了让这个加锁的过程更加高效。
下面,将重点分析一下加锁的几个过程:
1)无锁状态
不加锁,这种状态一般不会存在。如果真的存在,那么很有可能是被编译器把锁给优化掉了。
2)偏向锁状态:非必要,不加锁
当进入synchronized代码块当中之后,首先会进入到偏向锁的状态;
其实偏向锁,就是一个线程对对象尝试加锁的一种状态,并没有真正施加锁,而是先对于这个对象做一个标记。做标记这个过程,其实相比于真正加锁,还是轻量了不少的。
如果整个使用锁的过程当中,都没有出现锁竞争,那么这个标记,就会在线程离开synchronized之后释放;
如果另外一个线程同时也尝试对于同一个对象加锁,那么就会造成锁升级,转变为轻量级锁。
3)轻量级锁
对于synchronized,它的轻量级锁,是通过自旋锁的方式来实现的。
对于自旋锁的解释,也已经在这一篇文章当中提到了:
【JavaEE进阶】锁的特性_革凡成圣211的博客-CSDN博客Java锁的特性https://blog.csdn.net/weixin_56738054/article/details/128574608?spm=1001.2014.3001.5501
自旋锁虽然不会造成线程的阻塞等待,但是如果无法通过CAS获取到锁,就会一直在循环当中尝试获取锁。
如果获取到锁的线程很快就释放锁了,那么也就意味着自旋是划算的。
如果获取到锁的线程一直没有释放锁,那么这个自旋的过程是很消耗cpu资源的。
因此,当synchronized处于自旋锁的状态的时候,它的内部会有一个计数器,当计算的数量达到一定的数目之后,就停止自旋,升级为重量级锁。
4)重量级锁:挂起等待
重量级锁,会造成线程阻塞等待。这个过程,则是基于操作系统原生的API来实现的。
这个时候,如果线程进行了重量级锁的加锁过程,那么获取不到锁的线程就会被操作系统调度离开CPU内核,被放入阻塞队列当,暂时不参与CPU的运算调度。
重量级锁,因为涉及线程调度离开CPU,调度回到CPU的过程,相比起轻量级锁,会更
加消耗CPU的资源。
目前JVM,只支持锁升级的操作,不支持锁降级的操作。
二、锁消除
锁消除是发生在编译阶段的事件
编译器的智能判定,看当前代码是否真的需要加锁。
如果不需要加锁 ,代码当中也加锁了,那么这个锁就会被编译器消除。
经典现象:对于StringBuffer,如果单线程环境使用,那么编译器就会把这个锁消除掉。
三、锁粗化
锁的粒度
对于synchronized:它所包含的代码越多,粒度就越粗。包含的代码越少,粒度就越细。
在保证线程安全的情况下面,锁的粒度越细越好
对于ConcurrentHashMap来说,它的put方法的粒度就比Hashtable的put方法的粒度细很多。
锁粗化的好处
如果对于一些应用场景,两次加锁之间,间隙非常小。
但是由于加锁、解锁的过程也是需要一定的开销的。那不如直接使用一把大锁搞定,就不再反复加锁、解锁了。
这种变多把小锁为一把大锁的现象,就被称为锁的粗化