乐趣区

关于java:JAVA并发编程从字节码角度分析synchronized实现

1.idea 查看字节码 jclasslib 插件装置

2. 从字节码角度剖析 synchronized 实现

3. 总结

1.idea 查看字节码 jclasslib 插件装置
synchronize 这个关键字咱们必定曾经不生疏了,接下来咱们从字节码这个角度来进行分析一下,它为什么会有加锁的成果。咱们先装置一下 jclasslib 插件,不便咱们查看 java 的字节码。

点击 view –> show Bytecode With Jclasslib

就能够看到这个文件的字节码啦。

2. 从字节码角度剖析 synchronized 实现

2.1synchronized 同步代码块

public class LockByteDemo {final Object object = new Object();

    public void m1() {synchronized (object) {System.out.println("-------------hello sync");
            //throw new RuntimeException("6");
        }
    }
}

咱们对 m1() 这个 ssynchronized 同步代码块办法进行查看一下字节码。

咱们发现,它应用的是 monitorenter 指令 和 monitorexit 指令。

monitor:
其实每一个对象都有一个 monitor,就是监视器,当线程获取 monitor 胜利的时候,这个对象就被锁住了。

monitorenter 指令:
线程执行 monitorenter 就是为了尝试获取 monitor 的拥有权,过程为:

1)如果一个 monitor 的数值是 0,那么线程间接进入 monitor,并且将 monitor 置为 1,并将对象的抢占该线程置为该线程。
2)如果该线程曾经占用 monitor,则间接进入,monitor 数 +1(可重入锁)
3)如果该对象的抢占线程不是该线程,那么该线程就会被阻塞,直到 monitor 的数值变成 0,再次抢占。

monitorexit 指令:

执行 monitorexit 的线程必须是曾经领有该对象 monitor 的线程,执行 monitorexit 命令后,monitor 的进入数会减 1,当减为 0 时,其它线程就能够尝试取得 monitor 的所有权。

然而这里有一个疑难,为什么只有一个 monitorenter,然而有两个 monitorexit?

咱们能够思考一下,这其实是和 try/finally 是一个情理,咱们个别编程的时候,都要在 finally 里加一个解锁 unlock,避免异常情况的产生,那么这里也是一样的,为了避免代码出现异常,最初在进行 monitorexit 一下。

2.2synchronized 一般同步办法

咱们会发现,一般办法标记位多了一个 ACC_SYNCHRONIZED 拜访标记。

当咱们调用一个办法的时候,会先查看办法的 ACC_SYNCHRONIZED 拜访标记是否被设置,如果设置了,线程执行会先尝试获取 monitor,最初在办法实现的时候开释 monitor。

2.3synchronized 动态同步办法

动态同步办法的原理也是一样的,不过再多一个 ACC_STATIC 标记位,用来辨别是否动态同步办法。

3. 总结

明天咱们分析了 synchronized 的字节码角度实现,其实多减少这种内功的修炼,会让我写代码的时候,有一种不一样的感觉,以前写 synchronized 的时候,脑子里只有单单一个 synchronized 关键字,当初又会联想到字节码,可能就是今人说的,从看山是山,到看山不是山的转变。

退出移动版