Synchronized实现原理

Synchronized 三种锁类型(本质上都是依赖对象来锁)

this锁:当前实例锁,比如在方法里面通过锁住this
class锁:类对象锁
Object锁:对象实例锁
前面我们提到synchronized是依赖于对象的对象头中的Monitor来实现的锁功能,而从官方的虚拟机规范文档上可以看到Java中的synchronized同步的确是基于Monitor(管程)对象来实现的,
获取锁:进入管程对象(显式型:monitorenter指令),
释放锁:退出管程对象(显式型:monitorexit指令),


重量级锁也就是通常说synchronized的对象锁,锁标识位为10,其中【指针指向的是monitor对象】(也称为管程或监视器锁)的起始地址。
每个对象都存在着一个 monitor 与之关联,对象与其 monitor 之间的关系有存在多种实现方式,如monitor可以与对象一起创建销毁或当线
程试图获取对象锁时自动生成,但当一个monitor被某个线程持有后,它便处于【锁定状态】


在Java虚拟机(HotSpot)中,monitor是由【ObjectMonitor】实现的,其主要数据结构如下
ObjectMonitor() {
    _count        = 0; 			//记录个数,重入会加1
    _owner        = NULL;  		//获得ObjectMonitor对象的【线程】或基础锁

    _waiters      = 0, 			//等待线程数
    _WaitSet      = NULL; 		//处于【wait状态】的线程,会被加入到_WaitSet,这里是先拿到了锁然后调用了wait方法导致释放锁。
    _EntryList    = NULL; 		//处于【等待锁block状态】的线程,会被加入到该列表
}


monitor:monitor存在于堆中,什么是Monitor?我们可以把它理解为一个【同步工具】,也可以描述为一种同步机制,它通常被描述为一个对象。
与一切皆对象一样,所有的【Java对象是天生的Monitor】,每一个Java对象都有成为Monitor的潜质,因为在Java的设计中 ,每一个Java对象
自打娘胎里出来就带了一把看不见的锁,它叫做内部锁或者Monitor锁。

Synchronized实现原理_第1张图片

ObjectMonitor中有两个队列,
_WaitSet 和 _EntryList,用来保存ObjectWaiter对象列表( 每个等待锁的线程都会被封装成ObjectWaiter对象),
_owner指向持有ObjectMonitor对象的线程,

当多个线程同时访问一段同步代码时,
1、首先会进入 _EntryList 集合,
2、当线程获取到对象的monitor 后进入 _Owner 区域并把monitor中的owner变量设置为当前线程,同时monitor中的计数器count加13、若线程调用 wait() 方法,将释放当前持有的monitor,owner变量恢复为null,count自减1,同时该线程进入WaitSet集合中等待被唤醒。
4、若当前线程执行完毕也将释放monitor()并复位变量的值,以便其他线程进入获取monitor()。如下图所示:

由此看来,monitor对象存在于每个Java对象的对象头中markword内(存储的指针的指向)synchronized关键字便是通过这种方式获取锁的,也是为什么【Java中任意对象可以作为锁】的原因,
同时也是notify/notifyAll/wait等【方法存在于顶级对象Object】中的原因

你可能感兴趣的:(Synchronized,原理)