先来看个奇怪的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-锁膨胀的过程的更多相关文章

  1. JAVA锁的优化和膨胀过程

    转自:https://www.cnblogs.com/dsj2016/p/5714921.html https://cloud.tencent.com/developer/article/103675 ...

  2. java并发笔记之四synchronized 锁的膨胀过程(锁的升级过程)深入剖析

    警告⚠️:本文耗时很长,先做好心理准备,建议PC端浏览器浏览效果更佳. 本篇我们讲通过大量实例代码及hotspot源码分析偏向锁(批量重偏向.批量撤销).轻量级锁.重量级锁及锁的膨胀过程(也就是锁的升 ...

  3. java架构之路(多线程)synchronized详解以及锁的膨胀升级过程

    上几次博客,我们把volatile基本都说完了,剩下的还有我们的synchronized,还有我们的AQS,这次博客我来说一下synchronized的使用和原理. synchronized是jvm内 ...

  4. JAVA锁的膨胀过程和优化

    首先说一下锁的优化策略. 1,自旋锁 自选锁其实就是在拿锁时发现已经有线程拿了锁,自己如果去拿会阻塞自己,这个时候会选择进行一次忙循环尝试.也就是不停循环看是否能等到上个线程自己释放锁.这个问题是基于 ...

  5. JAVA锁的膨胀过程和优化(阿里)

    阿里的人问什么是锁膨胀,答不上来,回来做了总结: 关于锁的膨胀,synchronized的原理参考:深入分析Synchronized原理(阿里面试题) 首先说一下锁的优化策略. 1,自旋锁 自旋锁其实 ...

  6. synchronized(三) 锁的膨胀过程(锁的升级过程)深入剖析

    警告⚠️:本文耗时很长,先做好心理准备................哈哈哈 本篇我们讲通过大量实例代码及hotspot源码分析偏向锁(批量重偏向.批量撤销).轻量级锁.重量级锁及锁的膨胀过程(也就是 ...

  7. synchronized的实现原理——锁膨胀过程

    @ 目录 前言 正文 偏向锁 轻量锁 批量重偏向 批量撤销 重量锁 总结 前言 上一篇分析了优化后的synchronized在不同场景下对象头中的表现形式,还记得那个结论吗?当一个线程第一次获取锁后再 ...

  8. JAVA锁有哪些种类,以及区别(转)

    在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇文章介绍各种锁的分类.介绍的内容如下: 公平锁/非公平锁 可重入锁 独享锁/共享锁 互斥锁/读写锁 乐观锁/悲观锁 分段锁 偏向锁/轻量级 ...

  9. Java 锁优化

    一.重量级锁   Java中,Synchronized是通过对象内部的一个叫做监视器锁(monitor)来实现的.但是监视器锁本质又是依赖于底层的操作系统的Mutex Lock来实现的.而操作系统实现 ...

  10. JAVA锁机制-可重入锁,可中断锁,公平锁,读写锁,自旋锁,

    如果需要查看具体的synchronized和lock的实现原理,请参考:解决多线程安全问题-无非两个方法synchronized和lock 具体原理(百度) 在并发编程中,经常遇到多个线程访问同一个 ...

随机推荐

  1. 旷视6号员工范浩强:高二开始实习,“兼职”读姚班,25岁在CVPR斩获第四个世界第一...

    初来乍到,这个人说话容易让人觉得"狂". "我们将比赛结果提交上去,果不其然,是第一名的成绩."当他说出这句话的时候,表情没有一丝波澜,仿佛一切顺理成章. 他说 ...

  2. Activiti7流程定义

    一.什么是流程定义 流程定义是线下bpmn2.0标椎去描述业务流程,通常使用activiti-explorer(web控制台)或 activiti-eclipse-designer 插件对业务流程进行 ...

  3. inux上安装mysql

    目录 1.先验证是否安装了mysql 2.先下载mysql的repo源 3.安装mysql rpm包,执行命令: 4.安装mysql,执行命令: 5.登录然后重置密码,执行: 6.执行命令赋权,重启m ...

  4. coding++:Arrays.asList() - java.lang.UnsupportedOperationException异常处理

    这个异常遇到了才知道坑这么大,坑爹的方法. private String[] otherUserFromArray = new String[]{“3”, “4”, “发放”}; List<St ...

  5. nginx 报 502 bad gateway 分析解决

    出现nginx 502 bad gateway 问题,先从nginx端日志入手,分析排查原因. 1.排查问题 首先需要打开nginx错误日志. 编辑nginx.conf,默认路径在/usr/local ...

  6. 从谷歌 GFS 架构设计聊开去

    伟人说:“人多力量大.” 尼古拉斯赵四说:“没有什么事,是一顿饭解决不了的!!!如果有,那就两顿.” 研发说:“需求太多,人手不够.” 专家说:“人手不够,那就协调资源,攒人头.” 释义:一人拾柴火不 ...

  7. 从JDK源码学习Arraylist

    从今天开始从源码去学习一些Java的常用数据结构,打好基础:) Arraylist源码阅读: jdk版本:1.8.0 首先看其构造方法: 构造方法一: 第一种支持初始化容量大小,其中声明一个对象数组, ...

  8. 记一次JAVA进程导致Kubernetes节点CPU飙高的排查与解决

    一.发现问题 在一次系统上线后,我们发现某几个节点在长时间运行后会出现CPU持续飙升的问题,导致的结果就是Kubernetes集群的这个节点会把所在的Pod进行驱逐(调度):如果调度到同样问题的节点上 ...

  9. Unity Shader and Effects Cookbook问题记录

    1.p61的specular计算,涉及到的一个参数“_SpecColor”是在Unity的官方cginc文件(UnityLightingCommon.cginc)中,是直接赋颜色给这个参数,反应到你模 ...

  10. go 基本包

    像 fmt.os 等这样具有常用功能的内置包在 Go 语言中有 150 个以上,它们被称为标准库,大部分(一些底层的除外)内置于 Go 本身 unsafe: 包含了一些打破 Go 语言“类型安全”的命 ...