synchronized的实现原理
synchronized实现同步的基础具体表现为以下三种形式:
对于普通同步方法,锁的是当前实例对象;
对于静态同步方法,锁的是当前类的Class对象;
对于同步方法块,锁的是synchronized括号里配置的对象。
底层实现原理:
synchronized实现同步主要通过monitorenter和monitorexit指令实现的;monitorenter指令是在编译后插入到同步代码块的开始位置,而monitorexit是插入到方法结束和异常处,JVM要保证每个monitorenter必须有对应的monitorexit与之配对。任何对象都有一个monitor与之关联,当且一个monitor被持有后,它将处于锁定状态。线程执行到monitorenter指令时,将会尝试获取对象所对应的monitor的所有权,即尝试获得对象的锁。
synchronized用的锁存在Java对象头里的。
对象是数组类型,虚拟机用3个字宽存储对象头;
对象是非数组类型,虚拟机用2个字宽存储对象头;
对象头的存储结构
锁状态 | 25bit | 4bit | 1bit是否是偏向锁 | 2bit锁标志位 |
无锁状态 | 对象的hashCode | 对象分代年龄 | 0 | 01 |
从 无锁->偏向锁->轻量级锁->重量级锁 的锁升级时,Mark Work会有不同的变化
锁升级:
偏向锁:适用于单线程适用的情况,在不存在锁竞争的时候进入同步方法/代码块则使用偏向锁。
轻量级锁:适用于竞争较不激烈的情况(这和乐观锁的使用范围类似), 存在竞争时升级为轻量级锁,轻量级锁采用的是自旋锁,如果同步方法/代码块执行时间很短的话,采用轻量级锁虽然会占用cpu资源但是相对比使用重量级锁还是更高效。
重量级锁:适用于竞争激烈的情况,如果同步方法/代码块执行时间很长,那么使用轻量级锁自旋带来的性能消耗就比使用重量级锁更严重,这时候就需要升级为重量级锁。
本文来自博客园,作者:金玉良猿,转载请注明原文链接:https://www.cnblogs.com/LLFA/p/16488313.html