美文网首页
Synchronized 原理详解

Synchronized 原理详解

作者: qinghaihu | 来源:发表于2019-11-28 19:53 被阅读0次

    title: synchronized原理详解
    date: 2019-11-27
    author: qinghaihu
    categories:

    • 并发编程
      tags:
      • synchronized

    synchronized内置锁是一种对象锁(锁的是对象而非引用),作用粒度是对象,可以用来实现对临界资源的同步互斥访问,是可重入的。

    加锁方式

    1. 同步实例方法,锁的是当前实例对象
    2. 同步类方法,锁的是当前类对象(类加载后的Class对象)
    3. 同步代码块,锁的是括号里面的对象

    synchronized底层原理

    synchronized是基于JVM内置锁实现,通过内部对象Monitor(监视器锁)实现,基于进入与退出Monitor对象实现方法与代码块同步,监视器锁的实现依赖操作系统的Mutex lock(互斥锁)实现,它是一个重量级锁性能较低。当,JVM内置锁在1.5之后版本做了重大的优化,如锁粗化(Lock)、锁消除(Lock Elimination)、轻量级锁(Lightweight)、偏向锁(Biased Locking)、适应性自旋(Adaptive Spinning)等来减少锁操作的开销,内置锁的并发性能已经基本与Lock持平。

    synchronized关键字被编译成字节码后会被翻译成monitorenter 和monitorexit两条指令分别在同步块逻辑代码的起始位置与结束位置。

    Monitor锁.png

    这里以线程安全的单例设计模式为例,利用javap -verbose Singleton.class命令,我们看看编译后的部分汇编代码。

    public class Singleton {
    
        /**
         * 查看汇编指令
         * -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly -Xcomp
         */
        private volatile static Singleton myinstance;
    
        public static Singleton getInstance() {
            if (myinstance == null) {
                synchronized (Singleton.class) {
                    if (myinstance == null) {
                        myinstance = new Singleton();//对象创建过程,本质可以分文三步
                        //对象延迟初始化
                      }
                }
            }
            return myinstance;
        }
    
        public static void main(String[] args) {
            Singleton.getInstance();
        }
    }
    

    public static com.it.edu.jmm.Singleton getInstance();
    descriptor: ()Lcom/it/edu/jmm/Singleton;
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
    stack=2, locals=2, args_size=0
    0: getstatic #2 // Field myinstance:Lcom/it/edu/jmm/Singleton;
    3: ifnonnull 37
    6: ldc #3 // class com/it/edu/jmm/Singleton
    8: dup
    9: astore_0
    10: monitorenter
    11: getstatic #2 // Field myinstance:Lcom/it/edu/jmm/Singleton;
    14: ifnonnull 27
    17: new #3 // class com/it/edu/jmm/Singleton
    20: dup
    21: invokespecial #4 // Method "<init>":()V
    24: putstatic #2 // Field myinstance:Lcom/it/edu/jmm/Singleton;
    27: aload_0
    28: monitorexit
    29: goto 37
    32: astore_1
    33: aload_0
    34: monitorexit
    35: aload_1
    36: athrow
    37: getstatic #2 // Field myinstance:Lcom/it/edu/jmm/Singleton;
    40: areturn
    Exception table:
    from to target type
    11 29 32 any
    32 35 32 any

    每个同步对象都有一个自己的Monitor(监视器锁),加锁过程如下图所示:

    Monitor锁机制.png

    文章开头有提到,synchronized锁是一种对象锁,锁的是对象,那对象是如何记录的锁信息呢?这就不得不给提到对象的内存布局。

    HotSpot虚拟机中,对象在内存中存储的布局可以分为三块区域:对象头)、实例数(Instance Data)和对齐填充(Padding)。
    对象头:比如 hash码,对象所属的年代,对象锁,锁状态标志,偏向锁(线程)ID,偏向时间,数组长度(数组对象)等。
    实例数据:即创建对象时,对象中成员变量,方法等
    对齐填充:对象的大小必须是8字节的整数倍

    java对象内存结构.png

    相关文章

      网友评论

          本文标题:Synchronized 原理详解

          本文链接:https://www.haomeiwen.com/subject/lphiwctx.html