我们都知道在Java编程中多线程的同步使用synchronized关键字来标识,那么这个关键字在JVM底层到底是如何实现的呢。
我们先来思考一下如果我们自己实现的一个锁该怎么做呢:
第一点Java使用对象头来维护对象的上锁状态,第二点Java使用ObjectMonitor来维护等待中的线程及持有锁的线程****。
对象头中记录了锁的状态,Java中现在有三种锁状态偏向锁、轻量级锁、重量级锁。其中重量级锁就是用来和ObjectMonitor进行关联的,最开始Java只有重量级锁,但是重量级锁在有锁竞争的情况下需要阻塞线程,同时需要对ObjectMonitor的数据结构进行操作,比较耗费性能。后来Java为了提高锁的性能,引入了偏向锁和轻量级锁。这里需要注意偏向锁和轻量级锁与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中synchronized关键字上锁的的逻辑,这里的细节有很多,我们只描述大概的过程。
同时我们还要注意对象头中存储的hashcode的变化,对象刚开始创建的时候对象头中的hashcode还未生成,只有程序调用hashcode方法时候才会将hashcode存储到对象头中,这样可以保证不管用什么hashcode算法,同一个对象的hashcode在他的生命周期中都不会改变。
这里强调一下,如果对象处在重量级锁的时候,它就无法再次进入到轻量级锁状态,如果对象处在轻量级锁,它就无法进入到偏向锁的状态。只能等待对象进入无锁状态之后,再次进行判断。
Java程序执行到synchronized代码处,偏向锁的逻辑如下:
标签:java,数据库,作用,微信,淘宝,管理数据,安装配置,MySQL 来源:
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。