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

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 。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/563345.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java 类 解析_Java集合类解析 ***

collection集合Map集合Hashtable和HashMap的区别&#xff1a;Hashtable的方法是同步的&#xff0c;而HashMap的方法不是。HashMap可以将空值作为一个表的条目的key或value。Collection接口Collection接口是List、Set和Queue接口的父接口&#xff0c;该接口里定义的方法既可用于…

JVM的生命周期

1.加载&#xff08;Loading&#xff09;&#xff1a; 在加载阶段&#xff0c;JVM会找到并加载Java字节码文件。加载阶段分为三个步骤&#xff1a;通过类的全限定名找到对应的字节码文件&#xff0c;创建一个与该类相关的Class对象&#xff0c;将类的静态数据结构存储在方法区中…

java数组数据结构_Java数据结构之数组

自定义数组(面向对象编程)&#xff1a;直接上代码&#xff1a;package com.xingej.algorithm.datastructure.array;/*** 面向对象编程** 自定义类数组** 你一定要明白&#xff0c;这是在JDK基础之上的封装&#xff0c;要学会这种思路&#xff0c;其他框架如netty 也是在前者的基…

java项目如何单元测试_大家java web项目开发做单元测试吗?

java web项目测试用Web的测试工具&#xff0c;如HtmlUnit&#xff0c;JWebUnit等。main()方法就可以测试&#xff0c;在main方法中获得connection对象将他输出就可以了。如果正常输出一大串就是对了。例子&#xff1a;public class DBConnection {private static String url &…

python双素数_python双素数_用Python打印100以下的所有双素数对

^{bq}$这是一种基于筛分的方法&#xff0c;它有点短&#xff0c;速度快得多&#xff1a;def find_prime_pairs(n):sieve [True] * nif n > 0:sieve[0] Falseif n > 1:sieve[1] Falsefor number in range(2, int(n ** 0.5) 1):if sieve[number]:for index in range(nu…

python无所不能_python-列表

列表创建&#xff1a;# 方式一&#xff1a;(常用)s [1, 2, 小超银]print(s) # [1, 2, 小超银]# 方式二&#xff1a;(不常用)s1 list() # 空列表l1 list(123)print(l1) # [1, 2, 3]# 方式三&#xff1a;列表推导式l1 [i for i in range(1,5)]print(l1) # [1, 2, 3, 4]增&…

lvds接口屏线安装图解_五分钟让你学会液晶拼接屏安装方法

液晶拼接屏成为目前比较热门的大屏显示系统&#xff0c;技术比较成熟&#xff0c;清晰度高、维护方便&#xff0c;性价比也还不错&#xff0c;市场需求量较大。但是液晶拼接屏安装方法很多人并不了解&#xff0c;下面小编就来简单介绍一下。以46寸液晶拼接屏指导安装为例&#…

cmd255command.executereader()打印连接错误_打印经常遇到的几个问题,轻松解决

在平常的工作中&#xff0c;我们经常会遇到一些打印问题&#xff0c;今天就分享下几个常见的故障问题解决。wps/office文档一点击打印就卡死这种一般默认打印机设置的是其它电脑共享的情况下出现的&#xff0c;当与主机的连接出现异常或者主机的打印设置有问题时&#xff0c;就…

如何制定客户留存策略_商客通:办理石家庄400电话如何留存客户

【办理石家庄400电话如何留存客户】在如今理性消费的市场&#xff0c;400电话能够为在消费者心中为企业营造一份信任感&#xff0c;彰显企业关怀及企业责任感&#xff1b;为消费者提供畅达的通信渠道、完善的企业服务保障。石家庄400电话搬家不换号石家庄企业在公司搬迁或者员工…

普中51控制火焰传感器_汽车爆震传感器的工作原理及的检测方法、处理

汽车爆震传感器的工作原理及的检测方法、处理黄永刚1 爆震传感器的工作原理按照结构的不同&#xff0c;可以将汽车爆震传感器分为压电式非共振型爆震传感器、压电式共振型爆震传感器和压电式火花塞座金属垫型爆震传感器&#xff0c;又可以分为压电式爆震传感器和电感式爆震传感…

idb 怎么回复mysql_MysqliDb 库的一些使用简单技巧(php)

一.分页功能假设接口要接受输入&#xff1a;page, page_limit&#xff0c;key&#xff0c;value&#xff0c;table 来查询 table 中 key like value 的元组中以 page_limit 为 page size 时第 page 页的数据。要求输出为&#xff1a;{"count" > $count&#xff0c…

java绘制流程图_如何才能更好地绘制计算机毕业设计中各种图表

“ 毕设论文中的各种图表是不可或缺的&#xff0c;如果只是单纯的文字&#xff0c;或者图表较少&#xff0c;达不到要求的话&#xff0c;最终是通过不了答辩审核的&#xff01;”目前绘制图表的软件很多&#xff0c;比如VISIO等&#xff0c;切记尽量不要使用word软件进行绘制&a…

arcgis加载dwg显示一个点_Arcgis添加控制点配准校正影像,更新校正之后,其他软件打开之后,影像位置没有校正解决办法...

使用有偏移的两景影像srcImg.tif 和 refImg.tif举例&#xff0c;用refImg.tif为参考&#xff0c;把待校正影像srcImg.tif&#xff0c;与refImg.tif配准一致。原始影像如下所示&#xff1a;这里就不演示如何采集控制点了&#xff0c;大家可以搜索arcgis配准详细步骤&#xff1b;…

网页检测不到java无法打印_如果PC连接到网络打印机,如何检查java?

根据“How Network Printing Works”,它实际上取决于打印机的类型和它支持的协议.如果您知道打印机使用的IP和端口,并且您的打印机支持SNMP(仅选择协议),则可以使用SNMP协议1查询打印机以获取信息. Java libSNMP4j可以帮助您实现这一目标.我建议不要使用它,除非打印机,IP和端口…

空投坐标怎么看6_嗦粉不咯?桂林米粉店将分三四五星级,你怎么看? 旅行 6 月 4 日热点速递...

吃货们请听好&#xff0c;以下内容可能与你有关~来看今日好问广西无疑是嗦粉星人的圣地&#xff0c;桂林米粉、柳州螺蛳粉、南宁老友粉 ...... 用手指都不够数。这不&#xff0c;桂林发布「米粉新政」&#xff0c;从 7 月起桂林米粉店划分为三星级、四星级、五星级三个等级。如…

java list应用_java中list集合的应用

java中list集合的应用 1.数组列数据的添加与删除&#xff1a; List list new LinkedList(); list new ArrayList(); 产生一个数组列对象并建立双向连表。 连表分为单向连表和双向连表&#xff1b;单向连表就像&#xff1a;a 只能到 b&#xff0c;b 不能到 c&#xff1b;双向连…

ubuntu 自动加载ko_开屏广告太烦人?用这个只有 2M 的 App,助你自动跳过 5 秒等待...

手机上的什么按钮会让你不假思索点击&#xff1f;除了抢红包&#xff0c;恐怕就是应用启动页的「跳过广告」了。「跳过广告」会这么容易被叉掉吗&#xff1f;显然&#xff0c;如果不够快准狠&#xff0c;连戳几次没反应不说&#xff0c;还有可能在戳偏后继续忍受广告跳转……掐…

java union pay 代码_Java标记了union / sum类型

使用一个私有构造函数创建一个抽象类,并在类中嵌套“数据构造函数”(左侧和右侧静态工厂方法),以便它们可以看到私有构造函数,但没有其他任何东西可以有效地密封类型.使用抽象方法either来模拟详尽的模式匹配,在静态工厂方法返回的具体类型中适当地覆盖.实现便利方法(如fromLef…

怎样查看cudnn版本_tensorflowGPU版本踩坑记录

终于安装完成了tensorflow&#xff0c;写一下过程开心的记录一下之前按照网上的教程&#xff0c;装了半天&#xff0c;下对应的cuda和cudnn&#xff0c;搞了半天&#xff0c;结果is_gpu_avaliable()函数通不过&#xff0c;查了半天&#xff0c;只找到cuda和cudnn版本不对应&…

java继承调用先后_「继承顺序」JAVA继承顺序 - seo实验室

继承顺序当使用继承这个特性时&#xff0c;程序是如何执行的&#xff1b;继承的初始化顺序1.初始化父类再初始子类2.先执行初始化对象中属性&#xff0c;再执行构造方法中的初始化当使用继承这个特性时&#xff0c;程序是如何执行的呢&#xff0c;也就是说我们需要关注继承的初…