synchronized批量重偏向与批量撤销 终于等到了!阿里P8历时九个月整理,Java面试宝典,核心知识点笔记在此 “数字心脏”动态解析消费密码,国家级消费市场大数据联合实验室在上海先行先试 全世界运行着大约230亿台物联网设备,安全问题如何解? 物联网产业园&thinkplus解决方案中心国学讲座如期而至 都是程序员,凭什么他能站在鄙视链的顶端? 猛男必看!去小红书做程序员是种什么体验 drozer提示[Errno 2] No such file or directory 【STM32】NB-iOT BC35-G模块 AT指令应用设计指导(附代码) 【北京迅为】i.MX6ULL终结者编译LED汇编程序 Linux系统读写网卡PHY寄存器工具 洛谷:P1226 【模板】快速幂||取余运算(分治,数学) 【2020顶会KDD】AutoST:面向时空预测的高效神经网络学习模型 C/C++实现并查集disjoint_set的模板(带路径压缩优化) 实现一个百万级推送服务,除了它,还有谁 “健康守护者”——STM32标准库和HAL库的比较 程序员被公司辞退12天后,前领导要求回公司讲清代码,结果懵了 RTTR实现C++反射(1)集成rttr库 lotus node 远程运行 CCF历年4,5题收录 N卡 RTX3070/RTX3080/RTX3090挖矿算力推测 最高算力86MH 理论+实验:MySQL索引、事物与存储引擎 PostgreSQL JOIN 多表查询 TP框架实现Excel批量导入数据库数据 MySQL中的列转行 这次是真拯救了我,MySQL索引优化,explain讲得非常清楚了 Oracle快速入门(PLSQL编程) MySQL字符串拼接、截取 MySQL事务管理及存储引擎 《浪姐》万茜点赞宁静、郁可唯黑贴坐实?盗号者和程序员是背锅侠 程序员被公司辞退12天后,前领导要求回公司讲清代码,结果懵了 易语言大漠多线程foobar在游戏多窗口中时时显示输出信息 非科班,自学两年,复盘两个月,侥幸拿到头条、阿里offer 2020年全国数学建模大赛B题源代码以及模型的建立 (2) 2020年数学建模-校园供水系统智能管理 windows破解锁屏密码(亲测有效:再也不怕别人锁屏防你啦!) 清华大佬力荐的JVM学习路线+实战笔记+阿里真题,嚼碎吃透吊打面试官 打造多模块+高可用+高扩展Spring Cloud版分布式电商项目源码分享 Python爬虫入门教程 89-100 定个小目标,先用Python爬个一亿B站用户 五大分布式事务,你了解多少? 2020-09-12 九大核心专题,630页内容,熬夜23天吃透,我收割了3个大厂offer 防抖节流 防抖和节流 函数节流 debounce throttle 每天补充一点 一些零碎的小知识点 JavaScript作用域和作用域链知多少 01-jquery概述 简单概述JSONP原理 02-$符号-jquery与js相互转换 遇见 vue.js --------阿文的vue.js学习笔记(2)----- 基本使用 全国鞋服行业首个5G专项应用落地柒牌 自动搬运作业提升效率150% 大数据系统提高生产效率超10%
您的位置:首页 >计算机基础 >

synchronized批量重偏向与批量撤销

synchronized批量重偏向与批量撤销

批量重偏向:如果一个类的大量对象被一个线程T1执行了同步操作,也就是大量对象先偏向了T1,T1同步结束后,另一个线程也将这些对象作为锁对象进行操作,会导偏向锁重偏向的操作。批量撤销:当一个偏向锁如果撤销次数到达40的时候就认为这个对象设计的有问题;那么JVM会把这个对象所对应的类所有的对象都撤销偏向锁;并且新实例化的对象也是不可偏向的。

可以通过命令java -XX:+PrintFlagsFinal -version|grep 'BiasedLocking'来看JVM中的默认配置:

intx BiasedLockingBulkRebiasThreshold= 20{product}intx BiasedLockingBulkRevokeThreshold= 40{product}intx BiasedLockingDecayTime= 25000 {product}intx BiasedLockingStartupDelay = 4000{product}bool TraceBiasedLocking= false {product}bool UseBiasedLocking= true{product}
BiasedLockingBulkRebiasThreshold:偏向锁批量重偏向的默认阀值为20次。BiasedLockingBulkRevokeThreshold:偏向锁批量撤销的默认阀值为40次。BiasedLockingDecayTime:距上次批量重偏向25秒内,撤销计数达到40,就会发生批量撤销。每隔(>=)25秒,会重置在[20, 40)内的计数,这意味着可以发生多次批量重偏向。

批量重偏向(BulkRebias)

测试代码:

package com.morris.concurrent.syn.batch;import org.openjdk.jol.info.ClassLayout;import java.util.ArrayList;import java.util.List;import java.util.concurrent.TimeUnit;import java.util.concurrent.locks.LockSupport;public class BulkBias {private static Thread t1, t2;public static void main(String[] args) throws InterruptedException {// 延时产生可偏向对象TimeUnit.SECONDS.sleep(5);List<B> objects = new ArrayList<>(); // 创建50个对象,锁状态为101,匿名偏向锁for (int i = 0; i < 50; i++) {objects.add(new B());}t1 = new Thread(() -> {for (int i = 0; i < objects.size(); i++) {synchronized (objects.get(i)) { // 50个对象全部偏向t1 101}}LockSupport.unpark(t2);});t2 = new Thread(() -> {LockSupport.park();//这里面只循环了30次!!!for (int i = 0; i < 30; i++) {Object a = objects.get(i);synchronized (a) {//分别打印第19次和第20次偏向锁重偏向结果if (i == 18 || i == 19) {System.out.println("第" + (i + 1) + "次偏向结果");System.out.println((ClassLayout.parseInstance(a).toPrintable())); // 第19次轻量级锁00,第20次偏向锁101,偏向t2}}}});t1.start();t2.start();t2.join();System.out.println("打印list中第11个对象的对象头:");System.out.println((ClassLayout.parseInstance(objects.get(10)).toPrintable())); // 01 无锁System.out.println("打印list中第26个对象的对象头:");System.out.println((ClassLayout.parseInstance(objects.get(25)).toPrintable())); // 101 偏向t2System.out.println("打印list中第41个对象的对象头:");System.out.println((ClassLayout.parseInstance(objects.get(40)).toPrintable())); // 101 偏向t1}}class B {}

运行结果如下:

第19次偏向结果com.morris.concurrent.syn.batch.B object internals: OFFSETSIZE TYPE DESCRIPTION VALUE0 4(object header) 40 f3 bc 1d (01000000 11110011 10111100 00011101) (498922304)4 4(object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)8 4(object header) 43 c1 00 f8 (01000011 11000001 00000000 11111000) (-134168253) 12 4(loss due to the next object alignment)Instance size: 16 bytesSpace losses: 0 bytes internal + 4 bytes external = 4 bytes total第20次偏向结果com.morris.concurrent.syn.batch.B object internals: OFFSETSIZE TYPE DESCRIPTION VALUE0 4(object header) 05 69 6c 1e (00000101 01101001 01101100 00011110) (510421253)4 4(object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)8 4(object header) 43 c1 00 f8 (01000011 11000001 00000000 11111000) (-134168253) 12 4(loss due to the next object alignment)Instance size: 16 bytesSpace losses: 0 bytes internal + 4 bytes external = 4 bytes total打印list中第11个对象的对象头:com.morris.concurrent.syn.batch.B object internals: OFFSETSIZE TYPE DESCRIPTION VALUE0 4(object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1)4 4(object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)8 4(object header) 43 c1 00 f8 (01000011 11000001 00000000 11111000) (-134168253) 12 4(loss due to the next object alignment)Instance size: 16 bytesSpace losses: 0 bytes internal + 4 bytes external = 4 bytes total打印list中第26个对象的对象头:com.morris.concurrent.syn.batch.B object internals: OFFSETSIZE TYPE DESCRIPTION VALUE0 4(object header) 05 69 6c 1e (00000101 01101001 01101100 00011110) (510421253)4 4(object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)8 4(object header) 43 c1 00 f8 (01000011 11000001 00000000 11111000) (-134168253) 12 4(loss due to the next object alignment)Instance size: 16 bytesSpace losses: 0 bytes internal + 4 bytes external = 4 bytes total打印list中第41个对象的对象头:com.morris.concurrent.syn.batch.B object internals: OFFSETSIZE TYPE DESCRIPTION VALUE0 4(object header) 05 60 6c 1e (00000101 01100000 01101100 00011110) (510418949)4 4(object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)8 4(object header) 43 c1 00 f8 (01000011 11000001 00000000 11111000) (-134168253) 12 4(loss due to the next object alignment)Instance size: 16 bytesSpace losses: 0 bytes internal + 4 bytes external = 4 bytes total

运行结果分析:

当一个线程t1运行结束后,所有的对象都偏向t1。线程t2只对前30个对象进行了同步,0-18的对象会偏向锁(101)升级为轻量级锁(00),19-29的对象由于撤销次数达到20,触发批量重偏向,偏向线程t2。t2结束后,0-18的对象由轻量级锁释放后变成了无锁,19-29的对象偏向t2,30-49的对象还是偏向t1。

总结:批量重偏向会以class为单位,为每个class维护一个偏向锁撤销计数器,每一次该class的对象发生偏向撤销操作时,该计数器+1,当这个值达到重偏向阈值(默认20)时,JVM就认为该class的偏向锁有问题,因此会进行批量重偏向。

批量撤销(BulkRevoke)

测试代码如下:

package com.morris.concurrent.syn.batch;import org.openjdk.jol.info.ClassLayout;import java.util.ArrayList;import java.util.List;import java.util.concurrent.TimeUnit;import java.util.concurrent.locks.LockSupport;public class BulkBiasAndRevoke {private static Thread t1, t2, t3, t4;public static void main(String[] args) throws InterruptedException {TimeUnit.SECONDS.sleep(5); // 等待偏向延迟时间到达List<L> list = new ArrayList<>();for (int i = 0; i < 80; i++) {list.add(new L());}t1 = new Thread(() -> {for (int i = 0; i < 60; i++) {L l = list.get(i);synchronized (l) {}}LockSupport.unpark(t2);}, "t1");t2 = new Thread(() -> {LockSupport.park();for (int i = 0; i < 60; i++) {L l = list.get(i);synchronized (l) {}}}, "t2");t3 = new Thread(() -> {LockSupport.park();System.out.println("t3");for (int i = 0; i < 60; i++) {L l = list.get(i);// 0-18 01// 19-59 101 偏向t2synchronized (l) {// 0-59 00}// 0-59 01}}, "t3");t4 = new Thread(() -> {synchronized (list.get(65)) {System.out.println("t4 begin" + ClassLayout.parseInstance(list.get(65)).toPrintable()); // 101LockSupport.unpark(t3);try {TimeUnit.SECONDS.sleep(5);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("t4 end" + ClassLayout.parseInstance(list.get(65)).toPrintable()); // 00System.out.println("t4 end" + ClassLayout.parseInstance(list.get(66)).toPrintable()); // 101}}, "t1");t4.start();t1.start();t2.start();t3.start();t3.join();t4.join();System.out.println(ClassLayout.parseInstance(new L()).toPrintable()); // 01}}class L {}

运行结果如下:

t4 begincom.morris.concurrent.syn.batch.L object internals: OFFSETSIZE TYPE DESCRIPTION VALUE0 4(object header) 05 61 79 1e (00000101 01100001 01111001 00011110) (511271173)4 4(object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)8 4(object header) 43 c1 00 f8 (01000011 11000001 00000000 11111000) (-134168253) 12 4(loss due to the next object alignment)Instance size: 16 bytesSpace losses: 0 bytes internal + 4 bytes external = 4 bytes totalt4 endcom.morris.concurrent.syn.batch.L object internals: OFFSETSIZE TYPE DESCRIPTION VALUE0 4(object header) 28 ef c2 1d (00101000 11101111 11000010 00011101) (499314472)4 4(object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)8 4(object header) 43 c1 00 f8 (01000011 11000001 00000000 11111000) (-134168253) 12 4(loss due to the next object alignment)Instance size: 16 bytesSpace losses: 0 bytes internal + 4 bytes external = 4 bytes totalt4 endcom.morris.concurrent.syn.batch.L object internals: OFFSETSIZE TYPE DESCRIPTION VALUE0 4(object header) 05 00 00 00 (00000101 00000000 00000000 00000000) (5)4 4(object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)8 4(object header) 43 c1 00 f8 (01000011 11000001 00000000 11111000) (-134168253) 12 4(loss due to the next object alignment)Instance size: 16 bytesSpace losses: 0 bytes internal + 4 bytes external = 4 bytes totalcom.morris.concurrent.syn.batch.L object internals: OFFSETSIZE TYPE DESCRIPTION VALUE0 4(object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1)4 4(object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)8 4(object header) 43 c1 00 f8 (01000011 11000001 00000000 11111000) (-134168253) 12 4(loss due to the next object alignment)Instance size: 16 bytesSpace losses: 0 bytes internal + 4 bytes external = 4 bytes total
t1执行完后,0-59的对象偏向t1。t2执行完后,0-18的对象为无锁,19-59偏向t2。t3执行时由于之前执行过批量重偏向了,所以这里会升级为轻量级锁。t4休眠前对象65为匿名偏向状态,t4休眠后,由于触发了批量撤销,所以锁状态变为轻量级锁,所以批量撤销会把正在执行同步的对象的锁状态由偏向锁变为轻量级锁,而不在执行同步的对象的锁状态不会改变(如对象66)。

总结:批量重偏向和批量撤销是针对类的优化,和对象无关。偏向锁重偏向一次之后不可再次重偏向。当某个类已经触发批量撤销机制后,JVM会默认当前类产生了严重的问题,剥夺了该类的新实例对象使用偏向锁的权利。

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。