monitorenter指令是在编译后插入到同步代码块的开始位置,而monitorexit是插入到方法结 束处和异常处,JVM要保证每个monitorenter必须有对应的monitorexit与之配对
别从低到高依次是:无锁状态、偏向锁状态、轻量级锁状 态和重量级锁状态,
synchronized
一、偏向锁
适合只有一个线程在临界区执行
有两个线程1和2拥有同一个对象锁,假如线程1先进入临界区发现锁对象的markword后三位是100(即偏向无锁),就会进行cas操作把线程id存储在markword中,线程执行完毕后线程id依然保存在markword中。如果下次本线程执行发现线程id是相等的就直接执行。如果线程2执行发现id不相等就会将id换成自己的。如果成功线程2执行,如果失败说明线程1还没执行完毕表示发生了竞争就把锁升级为轻量级锁。
二、轻量级锁
自旋需要需要多核cpu的支持,适合多个线程在临界区执行.
轻量级锁在栈帧中会保存一个锁记录对象 recorder object,ro中保存了锁对象的引用且用cas替换锁对象的markword,如果成功那么markword中就保存锁记录的地址和状态00(表示轻量级锁),当线程执行完毕后就将用cas替换回来。如果期间发生了锁重入就在栈帧中在保存一个锁记录对象增加一个重入计数.在线程执行期间如果有其他线程需要执行,就会对比锁对象中的markword,发现保存的不是本线程的锁记录地址那么就会进行自旋操作.如果失败就会锁膨胀为重量级锁.
三、重量级锁
锁对象的markword中保存monitor的引用。