锁粗化:
如果存在连串的一系列操作都对同一个对象反复加锁和解锁,甚至加锁操作时出现在循环体中的,那即使没有线程竞争,频繁地进行互斥同步操作也会导致不必要地性能操作。比如JVM会检测到这样一连串地操作都是对同一个对象加锁,那么JVM会将加锁同步地范围扩展(粗化)到整个一系列操作的外部,只需要加锁一次就可以了。
轻量级锁:
相对于重量级锁而言,减少重量级锁对线程的阻塞带来地线程开销,从而提高并发性能。在一些情况下,同步代码块不存在共享数据,也就不存在竞争关系,此时可以使用轻量级锁。
线程执行同步块之前:
JVM在执行当前线程时,如果当前对象没有被锁定,那么锁标志位位01状态。
1. jvm首先会在当前线程栈帧中创建锁记录Lock Record。
2. jvm使用CAS操作将标记字段Mark Word拷贝到锁记录中。
3. 将对像锁中的Mark Word更新为指向Lock Record的指针。
4.对象Mark Word的锁标志位更新为(Mark Word中最后的2bit)00。
如果成功,表示该线程就有用了该对象的锁,该对象锁为轻量级锁状态。如果失败,jvm会检查当前的Mark Word中是否存在指向当前线程的栈帧的指针,如果有,说明该锁已经被获取,可以直接调用。如果没有,则表示被别的锁占有,就存在竞争关系,升级为重量级锁。
总结:
多个线程存在竞争情况下,为了保证共享数据安全性,其必须要加锁保护,但是加锁、释放锁操作是不小的系统性能开销。传统情况下,加锁保证了共享数据的安全性,但是也增加系统性能开销。为了在保证共享数据安全性前提下,同时降低系统性能开销,JVM在内置锁上做了非常多的优化,膨胀式的锁分配策略就是其一,根据线程竞争激烈程度不同,出现自旋锁、自适应自旋锁、偏向锁、轻量级锁、重量级锁。