Monitor结构:
static int i=0;
static final Object obj = new Object();
public static void main(String[] args) {
new Thread(() -> {
synchronized (obj) {
//临界区代码
log.debug("获得锁");
try {
// Thread.sleep(20000);
i++;
lock.wait(20000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "t1").start();
当调用Synchronized对对象加锁的时候,java代码的obj对象和操作系统提供的Monitor对象关联,obj对象中里面markword记着Monitor指针地址。Monitor对象中的owner就会记录当前线程t1,如果再有其他线程t2,t3进来的时候,先查看obj有没有Markword地址有没有关联Monitor,再查看owner有没有给其他线程占领。如果有,只能进入EntryList进行等待,t2,t3在EntryList中进入阻塞状态。
当t1执行完synchronized中,临界区所有代码,这时Monitor中的owner会空闲出来,会唤醒t2或者t3线程,假如t2给唤醒,owner对象更新为t2信息,t3继续在EntryList中阻塞。
0: getstatic
#2// <- lock引用(synchronized开始)
// 3: dup
// 4: astore_1// lock引用 -> slot 1
// 5: monitorenter// 将 lock对象 MarkWord 置为 Monitor 指针
// 6: getstatic#3// <- i
// 9: iconst_1// 准备常数 1
// 10: iadd// +1
// 11: putstatic#3// -> i
// 14: aload_1// <- lock引用
// 15: monitorexit// 将 lock对象 MarkWord 重置, 唤醒 EntryList
// 16: goto2419: astore_2// e -> slot 2
// 20: aload_1// <- lock引用21: monitorexit// 将 lock对象 MarkWord 重置, 唤醒 EntryList
// 22: aload_2// <- slot 2 (e)
// 23: athrow// throw e
// 24: return
字节码中,从monitorenter 进入锁方法,monitorexit释放锁,即使发生异常也会monitorexit。