双非本科准备秋招(18.2)—— 图解Monitor

对象头

普通对象

双非本科准备秋招(18.2)—— 图解Monitor_第1张图片

数组对象

双非本科准备秋招(18.2)—— 图解Monitor_第2张图片

        java中对象存储结构分为对象头(Header)、实例数据(Instance Date)和对齐填充(Padding)。

        对象头存储着Mark Word和Klass Word,通过Klass Word,程序才知道这个对象是一个什么对象。

        Mark Word占32位。结构如下,有五种不同的类型,重点记一下:

        01偏向锁、00轻量级锁、10重量级锁

双非本科准备秋招(18.2)—— 图解Monitor_第3张图片

Monitor

        每个java对象都可以关联一个Monitor对象,当用synchronized给对象上锁(重量级)之后,该对象头的MarkWord中就被设置指向Monitor对象的指针

图中流程:

        1、刚开始Monitor中Owner为null

        2、Thread1执行时,将Monitor所有者Owner置为Thread2。

        3、Thread1上锁时,若有其他线程执行synchronized,进入EntryList阻塞blocked

        4、Thread1执行完后,唤醒EntryList中的线程来竞争锁,竞争非公平

        5、Thread0之前获得过锁,但是不满足执行条件,进入等待Waiting状态。

双非本科准备秋招(18.2)—— 图解Monitor_第4张图片

注意:

1、synchronized 必须是进入同一个对象的 monitor 才有上述的效果!

2、不加 synchronized 的对象不会关联监视器,不遵从以上规则!

Synchronized原理

我们可以查看一下synchronized的字节码文件。

把如下代码反编译:

public class Test {
    static  int cnt = 0;
    static final Object lock = new Object();
    public static void main(String[] args) {
        synchronized (lock){
            cnt++;
        }
    }
}
public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=3, args_size=1
         0: getstatic     #2                  // Field lock:Ljava/lang/Object;
         3: dup
         4: astore_1
         5: monitorenter
         6: getstatic     #3                  // Field cnt:I
         9: iconst_1
        10: iadd
        11: putstatic     #3                  // Field cnt:I
        14: aload_1
        15: monitorexit
        16: goto          24
        19: astore_2
        20: aload_1
        21: monitorexit
        22: aload_2
        23: athrow
        24: return
      Exception table:
         from    to  target type
             6    16    19   any
            19    22    19   any

逐行分析:

         0: getstatic     #2                  // 引用lock对象
         3: dup
         4: astore_1                           // lock引用存到 slot1
         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: goto          24
        19: astore_2                          //e -> slot2
        20: aload_1                           // lock引用
        21: monitorexit                      //将lock对象MarkWord重置,唤醒EntryList
        22: aload_2                           // <- slot 2 (e)
        23: athrow                             //throw e
        24: return

        异常和正常都会正常解锁,不会造成死锁。下面有一个Exception table,当发生异常,会跳转到to指定的位置,保证锁的正常解锁。

你可能感兴趣的:(求职招聘,java,Monitor,并发编程,秋招,idea)