最近在整理自己的技术体系,关于并发编程,入门级知识重量级锁Synchronized,接下来试着解释这块知识。
jdk1.6之前,还没有引入“偏向锁”和”轻量级锁“,synchronized是依赖monitorenter指令和monitorexit指令实现的,而这个jvm指令集是依赖操作系统内核来完成的,就会涉及到用户态与内核态的数据传递,是比较耗性能的,所以,我们前辈称之为重量级锁。
对象的内存布局如下
如图,对象头markword有锁的标记位,可以表示当前对象的锁的四种状态,无锁、偏向锁、轻量级锁、重量级锁。
参考对象的内存布局
上面我们提到了,jdk1.6引入了锁的升级过程,锁分以下几种状态,
最开始是无锁状态
线程进入同步方法块,将自己的线程id通过CAS操作塞进对象头MarkWord中,升级为偏向锁
如果对象头MarkWord有偏向锁, 如果这个偏向锁threadId是自己,是直接使用该锁。 如果不是, 则判断指向的线程是否存活,如果该线程不处于活跃状态,则将对象头置为无锁,如果还存活,则等待它执行完成后释放锁,同时升级成轻量级锁.
偏向锁,自旋次数少,大部分的synchronized锁,都只是在无锁和偏向锁之间徘徊,消耗性能极低。
轻量级锁,自旋次数多,cpu消耗比较高,好在它停留在jvm层面的自旋操作,不涉及到用户态与内核态的切换.
重量级锁,使用monitorenter和monitorexit命令,依赖操作系统内存,涉及到用户态与内核态切换,比较耗费性能,不建议锁升级到此。