### Monitor对象
Monitor 对于每一个java对象都关联一个Monitor对象,如果使用synchronized关键,给对象上锁(重量级锁)之后,该对象的Mark word中就会设置指向Monitor对象的指针。下图是32位jvm的mark word 组成:
上图是Monitor的结构:
刚开始Monitor对象中的owner为null, 当线程Thread-2执行synchronized(obj)的时候,就会将monitor的owner置为Thread-2, 而且Monitor对象的owner只能有一个,所以当其他线程,在执行synchornized(obj)时,Thread-3,Thread-4,Thread-4 就会就如EntryList的队列里面。
当Thread-2的代码执行完毕,释放锁对象,同时唤醒EntryList中的Thread来竞争锁,而且是非公平的竞争。
### 轻量级锁:
所谓轻量级锁,就是多个线程在访问同一个锁对象的时候 是时间错开的,没有竞争的状态。还是使用synchronized
static Object object = new Object();
public static void method1() {
synchronized (object) {
//同步块A
method2();
}
}
private static void method2() {
synchronized (object) {
//同步块B
}
}
当Thread-1在执行上面的代码的时候,会在线程栈中的method1栈帧中创建Lock Record(锁记录对象) ,并且让Lock Record的Object Reference执行Object锁对象,并尝试用CAS替换Object的mark word, 将mark word的值放到Lock Record里面。如下图所示:
如果CAS失败,就会有下面两种情况:
1. 如果其他线程已经持有了Object对象的轻量级锁,那么对于当前线程来说,就是有竞争则要进入到锁膨胀过程。
2. 如果是当前自己的线程,则要执行synchronized锁重入,那么需要在当前线程的栈中在添加一条Lock Record记录。将Lock Record 中的Object Reference指向锁对象,话有Lock Reference第一个位置置为null. 过程如下图:
### 解锁的过程
在退出synchronized代码块(解锁)的时候,先判断Lock Record 里面的数据有为null,表示有重入,这是重置锁的记录,也就是把栈里面的Lock Record为null 的数据删除,直到剩下不为null的Lock Record的记录。开始还原object的Mark word操作。
利用CAS将Lock record 里面的数据(之前交换的数据)还原到Object里面的mark word中,结果成功则完成解锁,失败表示已经进入了锁膨胀,需要重量级锁的解锁过程。