java-锁膨胀的过程
先来看个奇怪的demo
public class A {
int i=0;
// boolean flag =false;
public synchronized void parse(){
i++;
JOLExample6.countDownLatch.countDown();
}
}
睡眠5秒,测试
public class JOLExample3 {
static A a;
public static void main(String[] args) throws Exception {
Thread.sleep(5000);
a= new A();
//a.hashCode();
out.println("befor lock");
out.println(ClassLayout.parseInstance(a).toPrintable());//无锁:偏向锁?
synchronized (a){
out.println("lock ing");
out.println(ClassLayout.parseInstance(a).toPrintable());
}
out.println("after lock");
out.println(ClassLayout.parseInstance(a).toPrintable());
}
}
我注释的那行代码是什么锁?看下结果

可以看出,没有线程持有锁的时候,是可偏向状态
然后我们把睡眠的代码注释掉,再测试一下
//Thread.sleep(5000);
看下结果

再看个两个线程的demo
首先是两个线程交替执行:
public class JOLExample10 {
static A a;
public static void main(String[] args) throws Exception {
a= new A();
Thread t1 = new Thread(){
@Override
public void run() {
synchronized (a){
out.println("t1 lock ing");
out.println(ClassLayout.parseInstance(a).toPrintable());
}
}
};
t1.start();
Thread.sleep(10000);//睡眠10秒,让main线程和t1线程交替执行
synchronized (a){//a b c c+++
out.println("main lock ing");
out.println(ClassLayout.parseInstance(a).toPrintable());
}
out.println("after lock");
out.println(ClassLayout.parseInstance(a).toPrintable());
}
}
看下结果

可以看出,交替执行时,是轻量锁
我们把睡眠的代码注释掉
//Thread.sleep(5000);//睡眠10秒,让main线程和t1线程交替执行
再次测试,
public class JOLExample10 {
static A a;
public static void main(String[] args) throws Exception {
a= new A();
Thread t1 = new Thread(){
@Override
public void run() {
synchronized (a){
out.println("t1 lock ing");
out.println(ClassLayout.parseInstance(a).toPrintable());
}
}
};
t1.start();
//Thread.sleep(5000);//睡眠10秒,让main线程和t1线程交替执行
synchronized (a){//a b c c+++
out.println("main lock ing");
out.println(ClassLayout.parseInstance(a).toPrintable());
}
Thread.sleep(5000);//睡眠10秒
out.println("after lock");
out.println(ClassLayout.parseInstance(a).toPrintable());
}
}
看下结果

自旋
自旋一段时间,可以理解为空转,时间很短,具体时间需要看jvm源码,如果在自旋时间内拿到了锁,就不再膨胀,如果还是拿不到锁,则膨胀为重量锁,如下
public static void main(String[] args) throws Exception {
a= new A();
Thread t1 = new Thread(){
@Override
public void run() {
synchronized (a){
out.println("t1 lock ing");
out.println(ClassLayout.parseInstance(a).toPrintable());
}
}
};
t1.start();
Thread.sleep(1670);//睡眠10秒,让main线程和t1线程交替执行
synchronized (a){//自旋一段时间,可以理解为时间很短,具体时间需要看jvm源码,如果在自旋时间内拿到了锁,就不再膨胀,如果还是拿不到锁,则膨胀为重量锁
out.println("main lock ing");
out.println(ClassLayout.parseInstance(a).toPrintable());
}
Thread thread2 = new Thread(){
@Override
public void run() {
synchronized (a){
out.println("t2 lock ing");
out.println(ClassLayout.parseInstance(a).toPrintable());
}
}
};
thread2.start();
/*Thread.sleep(10);
synchronized (a){
out.println("main lock ing");
out.println(ClassLayout.parseInstance(a).toPrintable());
}*/
//Thread.sleep(5000);//睡眠10秒,让main线程和t1线程交替执行
out.println("after lock");
out.println(ClassLayout.parseInstance(a).toPrintable());
}
如果调用wait方法,则立即变成重量锁
看下demo
public class JOLExample11 {
static A a;
public static void main(String[] args) throws Exception {
//Thread.sleep(5000);
a = new A();
out.println("befre lock");
out.println(ClassLayout.parseInstance(a).toPrintable());
Thread t1= new Thread(){
public void run() {
synchronized (a){
try {
synchronized (a) {
System.out.println("before wait");
out.println(ClassLayout.parseInstance(a).toPrintable());
a.wait();//如果调用wait方法,则立即变成重量锁
System.out.println(" after wait");
out.println(ClassLayout.parseInstance(a).toPrintable());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
t1.start();
Thread.sleep(7000);
synchronized (a) {
a.notifyAll();
}
}
}
看下结果

我们再看个synchronized膨胀的奇怪特性
让偏向锁无延迟启动
-XX:+UseBiasedLocking -XX:BiasedLockingStartupDelay=0
public class JOLExample12 {
static List<A> list = new ArrayList<A>();
public static void main(String[] args) throws Exception {
Thread t1 = new Thread() {
public void run() {
for (int i=0;i<10;i++){
A a = new A();
synchronized (a){
System.out.println("111111");
list.add(a);
}
}
}
};
t1.start();
t1.join();
out.println("befre t2");
//偏向
out.println(ClassLayout.parseInstance(list.get(1)).toPrintable());
Thread t2 = new Thread() {
int k=0;
public void run() {
for(A a:list){
synchronized (a){
System.out.println("22222");
if (k==4){
out.println("t2 ing");
//轻量锁
out.println(ClassLayout.parseInstance(a).toPrintable());
}
}
k++;
}
}
};
t2.start();
}
}
t1线程new10个对象,t2线程取第五个,看下结果
我们把new对象的数量改一下,改成20个,再来试一下
public class JOLExample12 {
static List<A> list = new ArrayList<A>();
public static void main(String[] args) throws Exception {
Thread t1 = new Thread() {
public void run() {
for (int i=0;i<20;i++){
A a = new A();
synchronized (a){
System.out.println("111111");
list.add(a);
}
}
}
};
t1.start();
t1.join();
out.println("befre t2");
//偏向
out.println(ClassLayout.parseInstance(list.get(1)).toPrintable());
Thread t2 = new Thread() {
int k=0;
public void run() {
for(A a:list){
synchronized (a){
System.out.println("22222");
if (k==19){
out.println("t2 ing");
//轻量锁
out.println(ClassLayout.parseInstance(a).toPrintable());
}
}
k++;
}
}
};
t2.start();
}
}
这里我们取第20个对象,查看对象头信息

我们可以看到,居然重偏向了,这里是jvm做的优化,20次以后就会冲偏向,小于20次时膨胀为轻量锁
这里我们称之为批量偏向,下面我们看下这个的原理

最后总结一下:轻量锁释放的时候将mark word重置为无锁状态,附上网络上的图

java-锁膨胀的过程的更多相关文章
- JAVA锁的优化和膨胀过程
转自:https://www.cnblogs.com/dsj2016/p/5714921.html https://cloud.tencent.com/developer/article/103675 ...
- java并发笔记之四synchronized 锁的膨胀过程(锁的升级过程)深入剖析
警告⚠️:本文耗时很长,先做好心理准备,建议PC端浏览器浏览效果更佳. 本篇我们讲通过大量实例代码及hotspot源码分析偏向锁(批量重偏向.批量撤销).轻量级锁.重量级锁及锁的膨胀过程(也就是锁的升 ...
- java架构之路(多线程)synchronized详解以及锁的膨胀升级过程
上几次博客,我们把volatile基本都说完了,剩下的还有我们的synchronized,还有我们的AQS,这次博客我来说一下synchronized的使用和原理. synchronized是jvm内 ...
- JAVA锁的膨胀过程和优化
首先说一下锁的优化策略. 1,自旋锁 自选锁其实就是在拿锁时发现已经有线程拿了锁,自己如果去拿会阻塞自己,这个时候会选择进行一次忙循环尝试.也就是不停循环看是否能等到上个线程自己释放锁.这个问题是基于 ...
- JAVA锁的膨胀过程和优化(阿里)
阿里的人问什么是锁膨胀,答不上来,回来做了总结: 关于锁的膨胀,synchronized的原理参考:深入分析Synchronized原理(阿里面试题) 首先说一下锁的优化策略. 1,自旋锁 自旋锁其实 ...
- synchronized(三) 锁的膨胀过程(锁的升级过程)深入剖析
警告⚠️:本文耗时很长,先做好心理准备................哈哈哈 本篇我们讲通过大量实例代码及hotspot源码分析偏向锁(批量重偏向.批量撤销).轻量级锁.重量级锁及锁的膨胀过程(也就是 ...
- synchronized的实现原理——锁膨胀过程
@ 目录 前言 正文 偏向锁 轻量锁 批量重偏向 批量撤销 重量锁 总结 前言 上一篇分析了优化后的synchronized在不同场景下对象头中的表现形式,还记得那个结论吗?当一个线程第一次获取锁后再 ...
- JAVA锁有哪些种类,以及区别(转)
在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇文章介绍各种锁的分类.介绍的内容如下: 公平锁/非公平锁 可重入锁 独享锁/共享锁 互斥锁/读写锁 乐观锁/悲观锁 分段锁 偏向锁/轻量级 ...
- Java 锁优化
一.重量级锁 Java中,Synchronized是通过对象内部的一个叫做监视器锁(monitor)来实现的.但是监视器锁本质又是依赖于底层的操作系统的Mutex Lock来实现的.而操作系统实现 ...
- JAVA锁机制-可重入锁,可中断锁,公平锁,读写锁,自旋锁,
如果需要查看具体的synchronized和lock的实现原理,请参考:解决多线程安全问题-无非两个方法synchronized和lock 具体原理(百度) 在并发编程中,经常遇到多个线程访问同一个 ...
随机推荐
- 模块 heapq_堆排序
_heapq_堆排序 该模块提供了堆排序算法的实现.堆是二叉树,最大堆中父节点大于或等于两个子节点,最小堆父节点小于或等于两个子节点. 创建堆 heapq有两种方式创建堆, 一种是使用一个空列表,然后 ...
- 学习 MyBatis 的一点小总结 —— 底层源码初步分析
目录 MyBatis 如何获取数据库源? MyBatis 如何获取 sql 语句? MyBatis 如何执行 sql 语句? MyBatis 如何实现不同类型数据之间的转换? 在过去程序员使用 JDB ...
- [noip模拟20170921]模版题
今天考的是一套很基础的模版题,但是我这种蒟蒻竟然还是没有AK,不得不说,蒟蒻和大佬的差别不是一点点啊 1.暴走的猴子(walk.pas/c/cpp) [题目描述] 从前有一个森林,森林里生活着一群 ...
- SQL server 2008 简介
一.简介 网状模型 关系模型(独立表) 拆分成有主键的表.连接表即可. 工资与奖金有了依赖关系.所以可以不保存奖金,计算得出结果. 二. 1. 2.环境配置 安装iis服务 https://jingy ...
- Flutter AbsorbPointer 与 IgnorePointer的区别
AbsorbPointer AbsorbPointer是一种禁止用户输入的控件,比如按钮的点击.输入框的输入.ListView的滚动等,你可能说将按钮的onPressed设置为null,一样也可以实现 ...
- 《Three.js 入门指南》3.1.1 - 基本几何形状-立方体(CubeGeometry)
3.1 基本几何形状 立方体(CubeGeometry) 构造函数: THREE.CubeGeometry(width, height, depth, widthSegments, heightSeg ...
- Redis 笔记(五)—— HASH 常用命令
添加和删除键值对的散列操作 命令 用例和描述 HMGET HMGET key-name key [key ...] —— 从散列里面获取一个或多个键的值 HMSET HMSET key-name ke ...
- Java中的数据结构-HashMap
Java数据结构-HashMap 目录 Java数据结构-HashMap 1. HashMap 1.1 HashMap介绍 1.1.1 HashMap介绍 1.1.2 HashMap继承图 1.2 H ...
- JVM 理解性学习(一)
重新学习,重新理解 1.类加载过程等 验证:.class 文件加载到 JVM 里的时候,会验证下该文件是否符合 JVM 规范. 准备:给实体类分配内存空间,以及给类变量(static 修饰)分配&qu ...
- 少儿编程Scratch第一讲:Scratch完美的初体验
素材及视频下载 链接:https://pan.baidu.com/s/1qX0T2B_zczcLaCCpiRrsnA提取码:xfp8 都说未来是人工智能.计算机程式控制的时代,如何让青少年接触计算机编 ...