本文已参与「新人创作礼」活动,一起开启掘金创作之路。
1、线程1持有偏向级锁; 2、线程2来竞争锁对象; 3、判断当前对象头是否是偏向锁; 4、判断拥有偏向锁的线程1是否还存在;
- 线程1不存在,直接设置偏向锁标识为0(线程1执行完毕后,不会主动去释放偏向锁)。使用cas替换偏向锁线程ID为线程2,锁不升级,仍为偏向锁;
- 线程1仍然存在,暂停线程1。设置锁标志位为00(变为轻量级锁),偏向锁为0;
5、从线程1的空闲monitor record中读取一条,放至线程1的当前monitor record中;
6、更新mark word,将mark word指向线程1中monitor record的指针;
7、继续执行线程1的代码;
8、锁升级为轻量级锁;
9、线程2自旋来获取锁对象;
3.2.1 偏向锁
==偏向锁:单线程竞争下==
当一段同步代码一直被同一个线程多次访问,由于只有一个线程,那么该线程在后续访问时便会自动获得锁。
线程并不会主动放弃偏向锁
偏向锁开启:
- 延迟时间为4秒;
偏向锁的撤销:
当有另外线程逐步来竞争锁的时候,就不能再使用偏向锁了,要升级为欸轻量级锁。竞争线程尝试CAS更新对象头但是失败了,那么会等待到==全局安全点==撤销偏向锁。全局安全的也即该时间点上没有字节码执行。
- 1属于上面所述的竞争失败,2属于竞争成功
- 升级为轻量级锁后,另一个线程在外面自旋,如果成功则进入,不成功则继续自旋。如果自旋次数太多,可能升级为重量级锁。
注:Java15后逐步废弃偏向锁,原因是维护成本过高,(JVM也在不断更新)
3.2.2 轻量级锁
两个线程,交替运行(基本上是轮流执行),锁的竞争不激烈,不必升级到重量级锁去阻塞线程。
Java6之后使用自适应自旋锁
轻量级锁和偏向锁区别:
3.2.3 重量级锁
四、参考资料
1、Java并发编程的艺术 方腾飞等著; 2、黑马JUC编程; 3、大厂学苑JUC 4、深入理解Java虚拟机