HotSpot VM内置锁的同步机制简述:

HotSpot VM采用三中不同的方式实现了对象监视器——Object Monitor,并且可以在这三种实现方式中自动切换。偏向锁通过在Java对象的对象头markOop中install一个JavaThread指针的方式实现了这个Java对象对此Java线程的偏向,并且只有该偏向线程能够锁定Lock该对象。但是只要有第二个Java线程企图锁定这个已被偏向的对象时,偏向锁就不再满足这种情况了,然后呢JVM就将Biased Locking切换成了Basic Locking(基本对象锁)。Basic Locking使用CAS操作确保多个Java线程在此对象锁上互斥执行。如果CAS由于竞争而失败(第二个Java线程试图锁定一个正在被其他Java线程持有的对象),这时基本对象锁因为不再满足需要从而JVM会切换到膨胀锁 - ObjectMonitor。不像偏向锁和基本对象锁的实现,重量级锁的实现需要在Native的Heap空间中分配内存,然后指向该空间的内存指针会被装载到Java对象中去。这个过程我们称之为锁膨胀。

降级的目的和过程:

因为BasicLocking的实现优先于重量级锁的使用,JVM会尝试在SWT的停顿中对处于“空闲(idle)”状态的重量级锁进行降级(deflate)。这个降级过程是如何实现的呢?我们知道在STW时,所有的Java线程都会暂停在“安全点(SafePoint)”,此时VMThread通过对所有Monitor的遍历,或者通过对所有依赖于MonitorInUseLists值的当前正在“使用”中的Monitor子序列进行遍历,从而得到哪些未被使用的“Monitor”作为降级对象。

可以降级的Monitor对象:

重量级锁的降级发生于STW阶段,降级对象就是那些仅仅能被VMThread访问而没有其他JavaThread访问的Monitor对象。

HotSpot VM中的实现:

上述降级过程在HotSpot VM中的实现,可以参考:

void ObjectSynchronizer::deflate_idle_monitors() {

assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");

int nInuse = 0 ; // currently associated with objects int nInCirculation = 0 ; // extant int nScavenged = 0 ; // reclaimed bool deflated = false;

ObjectMonitor * FreeHead = NULL ; // Local SLL of scavenged monitors ObjectMonitor * FreeTail = NULL ;

TEVENT (deflate_idle_monitors) ;

// Prevent omFlush from changing mids in Thread dtor's during deflation// And in case the vm thread is acquiring a lock during a safepoint// See e.g. 6320749 Thread::muxAcquire (&ListLock, "scavenge - return") ;

if (MonitorInUseLists) {

int inUse = 0;

for (JavaThread* cur = Threads::first(); cur != NULL; cur = cur->next()) {

nInCirculation+= cur->omInUseCount;

int deflatedcount = walk_monitor_list(cur->omInUseList_addr(), &FreeHead, &FreeTail);

cur->omInUseCount-= deflatedcount;

// verifyInUse(cur); nScavenged += deflatedcount;

nInuse += cur->omInUseCount;

}

// For moribund threads, scan gOmInUseList if (gOmInUseList) {

nInCirculation += gOmInUseCount;

int deflatedcount = walk_monitor_list((ObjectMonitor **)&gOmInUseList, &FreeHead, &FreeTail);

gOmInUseCount-= deflatedcount;

nScavenged += deflatedcount;

nInuse += gOmInUseCount;

}

} else for (ObjectMonitor* block = gBlockList; block != NULL; block = next(block)) {

// Iterate over all extant monitors - Scavenge all idle monitors. assert(block->object() == CHAINMARKER, "must be a block header");

nInCirculation += _BLOCKSIZE ;

for (int i = 1 ; i < _BLOCKSIZE; i++) {

ObjectMonitor* mid = &block[i];

oop obj = (oop) mid->object();

if (obj == NULL) {

// The monitor is not associated with an object.// The monitor should either be a thread-specific private// free list or the global free list.// obj == NULL IMPLIES mid->is_busy() == 0 guarantee (!mid->is_busy(), "invariant") ;

continue ;

}

deflated = deflate_monitor(mid, obj, &FreeHead, &FreeTail);

if (deflated) {

mid->FreeNext = NULL ;

nScavenged ++ ;

} else {

nInuse ++;

}

}

}

MonitorFreeCount += nScavenged;

// Consider: audit gFreeList to ensure that MonitorFreeCount and list agree.

if (ObjectMonitor::Knob_Verbose) {

::printf ("Deflate: InCirc=%d InUse=%d Scavenged=%d ForceMonitorScavenge=%d : pop=%d free=%d\n",

nInCirculation, nInuse, nScavenged, ForceMonitorScavenge,

MonitorPopulation, MonitorFreeCount) ;

::fflush(stdout) ;

}

ForceMonitorScavenge = 0; // Reset

// Move the scavenged monitors back to the global free list. if (FreeHead != NULL) {

guarantee (FreeTail != NULL && nScavenged > 0, "invariant") ;

assert (FreeTail->FreeNext == NULL, "invariant") ;

// constant-time list splice - prepend scavenged segment to gFreeList FreeTail->FreeNext = gFreeList ;

gFreeList = FreeHead ;

}

Thread::muxRelease (&ListLock) ;

if (ObjectMonitor::_sync_Deflations != NULL) ObjectMonitor::_sync_Deflations->inc(nScavenged) ;

if (ObjectMonitor::_sync_MonExtant != NULL) ObjectMonitor::_sync_MonExtant ->set_value(nInCirculation);

// TODO: Add objectMonitor leak detection.// Audit/inventory the objectMonitors -- make sure they're all accounted for. GVars.stwRandom = os::random() ;

GVars.stwCycle ++ ;

}

补充说明:JEP - Concurrent Monitor Deflation,旨在通过并发手段解决重量级锁降级过程中的效率问题,可以参考:JEP draft: Concurrent Monitor Deflation 。

java idle 机制_HotSpot VM重量级锁降级机制的实现原理相关推荐

  1. java 锁降级 知乎_HotSpot VM重量级锁降级机制的实现原理

    HotSpot VM内置锁的同步机制简述: HotSpot VM采用三中不同的方式实现了对象监视器--Object Monitor,并且可以在这三种实现方式中自动切换.偏向锁通过在Java对象的对象头 ...

  2. 偏向锁,轻量级锁,重量级锁(java)

    轻量级锁是JDK 1.6之中加入的新型锁机制,它名字中的"轻量级"是相对于使用操作系统互斥量来实现的传统锁而言的,因此传统的锁机制就称为"重量级"锁.首先需要强 ...

  3. (JUC)图文并茂!!!! 超详细 偏向锁VS轻量级锁VS重量级锁VS自旋

    偏向锁,轻量级锁,重量级锁 前言 java对象内存布局 (1)重量级锁(Moniter) (2)轻量级锁 锁膨胀.自旋.自适应自旋 (3)偏向锁(以64位虚拟机为例) 2.偏向锁撤销的3种情况 (1) ...

  4. 锁升级过程(无锁、偏向锁、轻量级锁、重量级锁)

    文章目录 Synchronized锁升级的背景 Synchronized的性能变化 Java5之前,用户态和内核态之间的切换 为什么每个对象都可以称为一把锁? Java6开始优化Synchronize ...

  5. 锁,CAS,Synchronized 原理

    作者:~小明学编程 文章专栏:JavaEE 格言:热爱编程的,终将被编程所厚爱. 目录 常见的锁 悲观锁与乐观锁 悲观锁 乐观锁 读写锁 重量级锁 vs 轻量级锁 挂起等待锁和自旋锁 公平锁和非公平锁 ...

  6. java 重量级锁_轻量级锁和重量级锁的区别分别有哪些?java锁机制教程

    Java中有着各种锁机制,今天我们要说的就是其中两种状态,轻量级锁与重量级锁,小伙伴们知道它们的区别分别有哪些吗?下面来了解一下吧. 首先我们了解一下有哪些锁状态吧 锁的状态总共有四种:无锁状态.偏向 ...

  7. 【Java 并发编程】线程锁机制 ( 锁的四种状态 | 无锁状态 | 偏向锁 | 轻量级锁 | 重量级锁 | 锁竞争 | 锁升级 )

    文章目录 一.悲观锁示例 ( ReentrantLock ) 二.重量级锁弊端 三.锁的四种状态 ( 无锁状态 | 偏向锁 | 轻量级锁 | 重量级锁 ) 四.锁的四种状态之间的转换 ( 无锁状态 - ...

  8. 【Java 并发编程】线程锁机制 ( 线程安全 | 锁机制 | 类锁 | 对象锁 | 轻量级锁 | 重量级锁 )

    文章目录 一.线程安全 二.锁机制 ( 类锁 | 对象锁 ) 三.锁分类 ( 轻量级锁 | 重量级锁 ) 一.线程安全 多个线程同时访问 同一个共享变量 时 , 只要能保证 数据一致性 , 那么该变量 ...

  9. Java中的锁机制 -- 乐观锁、悲观锁、自旋锁、可重入锁、读写锁、公平锁、非公平锁、共享锁、独占锁、重量级锁、轻量级锁、偏向锁、分段锁、互斥锁、同步锁、死锁、锁粗化、锁消除

    文章目录 1. Java中的锁机制 1.1 乐观锁 1.2 悲观锁 1.3 自旋锁 1.4 可重入锁(递归锁) 1.5 读写锁 1.6 公平锁 1.7 非公平锁 1.8 共享锁 1.9 独占锁 1.1 ...

最新文章

  1. excel操作技巧记录(实时更新)
  2. php禁止某个链接,php – 使用htaccess忽略链接的某些部分
  3. java并发Exchanger的使用
  4. webRTC——浏览器里的音视频通话 1
  5. c语言配电自动化,我是电气工程及其自动化专业的要学C语言吗?
  6. C++ 通讯录设计(二)
  7. 互联网运营遇到瓶颈?这套数据运营体系,高手和小白都必看
  8. zplane函数怎么用m文件调用_matlab中cla用法
  9. 关于Unity中的transform组件(二)
  10. 美国科技股昨日普遍下跌:华尔街受特朗普影响抛售科技股票
  11. Pyspark:NLP(文本分类)
  12. linux终端安装deb文件,如何通过命令行安装.deb文件?
  13. meta标签http-equiv属性实现自动刷新页面和重定向
  14. 2018计算机考研时间表,2018年考研时间与考试各科目的日程安排
  15. cocoapods的安装
  16. 高通骁龙820A凭什么能赢得众多车厂的芳心
  17. 数值模拟偏微分方程的三种方法介绍
  18. IBM放弃SoftLayer品牌 将其归入Bluemix之中
  19. 超低功耗 段码LCD液晶显示驱动IC-VKL060 SSOP24 15SEG*4COM,超低工作电流约7.5微安,多用于传感器/水电表/工控仪表等
  20. 汽车动力性matlab程序,汽车动力性计算matlab程序

热门文章

  1. 将dll制作成控件_全国首例将“影视作品”制作成“网络图片集”方式侵权案宣判...
  2. okhttp 工具类_日语学习工具推荐,小白必备!
  3. domino流程图_OA实施工程师一线解读Java与Domino优劣
  4. docker mysql配置 丢失_Ubuntu16.04服务器环境配置 – Docker、MySQL、Redis
  5. 忽视大小写函数_使用率低但功能强大的6个Excel函数公式应用技巧解读!
  6. Chrome用户不喜新版:宁用其他浏览器也不要用旧版本
  7. ECharts 仪表盘的轴线宽度修改
  8. linux下opencv读取图片并存储到mysql数据库中
  9. java基础学习笔记(三)
  10. 我的世界服务器修改末地难度,涨姿势啦!我的世界老司机带你解锁进入末地的高难度姿势!...