编程语言
首页 > 编程语言> > Java锁的逻辑(结合对象头和ObjectMonitor)

Java锁的逻辑(结合对象头和ObjectMonitor)

作者:互联网

我们都知道在Java编程中多线程的同步使用synchronized关键字来标识,那么这个关键字在JVM底层到底是如何实现的呢。
我们先来思考一下如果我们自己实现的一个锁该怎么做呢:

  1. 首先肯定要有个标记记录对象是否已经上锁,执行同步代码之前判断这个标志,如果对象已经上锁线程就阻塞等待锁的释放。
  2. 其次要有一个结构体来维护这些等待中的线程,锁释放后来遍历这些线程让他们去抢锁。

第一点Java使用对象头来维护对象的上锁状态,第二点Java使用ObjectMonitor来维护等待中的线程及持有锁的线程****。

对象头

对象头中记录了锁的状态,Java中现在有三种锁状态偏向锁、轻量级锁、重量级锁。其中重量级锁就是用来和ObjectMonitor进行关联的,最开始Java只有重量级锁,但是重量级锁在有锁竞争的情况下需要阻塞线程,同时需要对ObjectMonitor的数据结构进行操作,比较耗费性能。后来Java为了提高锁的性能,引入了偏向锁和轻量级锁。这里需要注意偏向锁和轻量级锁与ObjectMonitor没有任何关联,后面会做详细介绍。

ObjectMonitor

Java会为每一个对象和对象的Class对象分配一个ObjectMonitor对象,他是一个C++结构体,ObjectMonitor用来维护当前持有锁的线程,阻塞等待锁释放的线程链表,调用了wait阻塞等待notify的线程链表。这里不做过多描述,具体的维护逻辑可以搜索其他博客。

//结构体如下
ObjectMonitor::ObjectMonitor() {  
  _header       = NULL;  
  _count       = 0;  
  _waiters      = 0,  
  _recursions   = 0;       //线程的重入次数
  _object       = NULL;  
  _owner        = NULL;    //标识拥有该monitor的线程
  _WaitSet      = NULL;    //等待线程组成的双向循环链表,_WaitSet是第一个节点
  _WaitSetLock  = 0 ;  
  _Responsible  = NULL ;  
  _succ         = NULL ;  
  _cxq          = NULL ;    //多线程竞争锁进入时的单向链表
  FreeNext      = NULL ;  
  _EntryList    = NULL ;    //_owner从该双向循环链表中唤醒线程结点,_EntryList是第一个节点
  _SpinFreq     = 0 ;  
  _SpinClock    = 0 ;  
  OwnerIsThread = 0 ;  
}  

Java中的锁的逻辑

下面来描述一下Java中synchronized关键字上锁的的逻辑,这里的细节有很多,我们只描述大概的过程。
同时我们还要注意对象头中存储的hashcode的变化,对象刚开始创建的时候对象头中的hashcode还未生成,只有程序调用hashcode方法时候才会将hashcode存储到对象头中,这样可以保证不管用什么hashcode算法,同一个对象的hashcode在他的生命周期中都不会改变。
这里强调一下,如果对象处在重量级锁的时候,它就无法再次进入到轻量级锁状态,如果对象处在轻量级锁,它就无法进入到偏向锁的状态。只能等待对象进入无锁状态之后,再次进行判断。

偏向锁

Java程序执行到synchronized代码处,偏向锁的逻辑如下:

  1. 检查对象头中的hashcode是否生成,生成过hashcode的对象无法进入偏向锁(这是因为偏向锁设计时,没有地方用来备份hashcode)。
  2. 检查对象头中的锁标志位是否是01,如果不是说明对象处在其他锁的状态,则执行其他锁的逻辑。
  3. 如果偏向锁的线程ID是自己的线程ID则直接执行同步代码块,说明之前此线程已经获取到了锁。
  4. 如果偏向锁ID不是自己的线程ID,通过CAS算法尝试偏向锁的线程ID,如果成功了就获取到锁,直接执行同步代码。如果失败的话说明有线程获取了偏向锁,此时线程会请求那个持有锁的线程释放锁。
  5. 如果持有锁的线程还在同步代码中,则无法释放锁,这个时候锁会膨胀为轻量级锁。膨胀的的时候会修改对象头为轻量级锁。
  6. 同步代码执行完成后,线程并不会重置对象头的数据,即不会释放锁,以便下次再次执行的时候可以直接进入同步代码。

标签:java,数据库,作用,微信,淘宝,管理数据,安装配置,MySQL
来源: