简单谈谈synchronized的实现原理

Java中每一个对象都可以作为锁,对于以下情况:
普通同步方法,锁是当前实例对象
静态同步方法,锁是当前类的class对象
同步方法块,锁是括号里面的对象

看看synchronized的代码的代码及字节码文件


synchronized代码.png

字节码.png

从字节码文件可以看出,同步代码块是使用monitorenter和monitorexit指令实现的,而且monitorenter和monitorexit是成对出现的,monitorenter指令插入到同步代码块的开始位置,monitorexit指令插入到同步代码块的结束位置,每一个monitorenter与monitorexit对应就相当于加锁和释放锁。当且一个monitor被持有之后,他将处于锁定状态。线程执行到monitorenter指令时,将会尝试获取对象所对应的monitor所有权,即尝试获取对象的锁。

继续深入了解synchronized之前,先来谈谈Java对象头,Monitor。
在 Hotspot 虚拟机中,对象在内存中的布局可以分为3块区域:对象头、实例数据和对齐填充;
而对象头主要包括两部分数据:Mark Word(标记字段)、Klass Pointer(类型指针)。其中Klass Point是是对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例,Mark Word用于存储对象自身的运行时数据,它是实现轻量级锁和偏向锁的关键,所以下面将重点阐述

Mark Word。 Mark Word用于存储对象自身的运行时数据,如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程 ID、偏向时间戳等等。Mark Word在不同的锁状态下存储的内容不同,在32位JVM中的存储结构


对象头存储结构.png

说白了,对象头存储的就是锁的状态信息,即锁标志位;

再来说说Monitor
Monitor是一种同步机制,Monitor是内置于任何一个Java对象中的,syncrhoized利用monitor来实现加锁解锁,故syncrhoized又叫做内置锁,monitor的本质是依赖于底层操作系统的Mutex Lock实现。
即对于monitor对象:
1)每个java对象都拥有一个Monitor锁。
2)当一个monitor被持有后,它将处于锁定状态。
其实syncrhoized就是通过monitor实现的,但其实syncrhoized(lock)加锁时,用到的其实只是lock对象内置的monitor而已;一个对象的monitor是唯一的,相当于一个唯一的许可证。拿到许可证的线程才可以执行,执行完后释放对象的monitor才可以被其他线程获取。

总结来说就是,syncrhoized使用了对象内置锁来实现同步,在对象头中保存了锁的标志位(锁的状态),在JVM层面的体现就是monitorenter和monitorexit,从monitorenter进入同步块,从monitorexit离开同步快,释放锁,修改对象的对象头信息,而往更深入一点,monitor的实现依赖于操作系统。

你可能感兴趣的:(简单谈谈synchronized的实现原理)