synchronized 在jdk 1.7之前是重量级锁,独占锁,非公平锁。
jdk1.7之后,synchronized引入了 偏向锁,自旋锁,轻量级锁,重量级锁
- 自旋锁
当线程在获取锁的时候,如果发现锁已经由其他线程获得,这时候线程会先进行自旋,就是循环。如果在循环次数内这个线程得到了锁,那么他就进入。如果没有就转到轻量级锁
- 轻量级锁
代码进入同步块的时候,如果对象没有被锁定 虚拟机会在当前栈帧下创建一个lock record的锁记录空间,用来存储锁对象 markword的拷贝。然后虚拟机将使用cas操作将markword更新为指向lock record的指针,如果更新成功 那这个线程就拥有了锁。并更新锁对象的markword 为00 ,表示锁对象处于轻量级锁。
如果更新失败,就说明有其他线程竞争这个锁,如果有2条线程以上,轻量级锁就会升级为重量级锁。
在没有锁竞争的情况下 使用cas 操作,就避免互斥的开销
- 偏向锁
轻量级锁是在没有锁竞争的情况下,使用cas 操作 去除互斥的操作。那么偏向锁就是在没有锁竞争的情况下,连cas都不用了。
锁会偏向第一个获取它的那个线程。hotpost作者认为,在大多数情况下是没有锁竞争的,并且同一个线程 会重复获得这一把锁。添加偏向锁 就是为了让获得锁的代价更低
当一个线程获取到锁的时候,会使用cas操作,把当前线程的id记录到锁对象的markword中。
以后这个线程在进入和退出这个同步块的时候,只需要检查下markword中的线程id 是不是自己就可以了。
当有另外一个线程去尝试获得锁的时候,偏向锁就宣告结束。