先来看个奇怪的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. MySQL5.6 选项和变量整理

    MySQL5.6 选项和变量整理  --allow-suspicious-udfs 这个选项控制是否用户定义函数只有一个xxx符号用于主函数加载.默认,该选项是关闭并且只具有至少一个辅助符号的UDFs ...

  2. OpenCV-Python OpenCV中的K-Means聚类 | 五十八

    目标 了解如何在OpenCV中使用cv.kmeans()函数进行数据聚类 理解参数 输入参数 sample:它应该是np.float32数据类型,并且每个功能都应该放在单个列中. nclusters( ...

  3. OpenCV-Python 对极几何 | 五十一

    目标 在本节中 我们将学习多视图几何的基础知识 我们将了解什么是极点,极线,极线约束等. 基础概念 当我们使用针孔相机拍摄图像时,我们失去了重要信息,即图像深度. 或者图像中的每个点距相机多远,因为它 ...

  4. macOS 去掉系统软件更新红点提示

    当前系统提示更新到macOS Catalina .打开终端执行以下命令: 第一步运行: sudo softwareupdate --ignore "macOS Catalina" ...

  5. 算法修炼之路——【链表】Leetcode24 两两交换链表中的节点

    题目描述 给定一单链表,两两交换其中相邻的节点,并返回交换后的链表. 你不能只是简单的改变节点内部的值,而是需要实际的进行节点交换. 示例: 输入:head = [1, 2, 3, 4] 输出:hea ...

  6. Matlab——m_map指南(3)——实例

    m_map 实例 1. clear all m_proj('ortho','lat', 48,'long',-123');%投影方式,范围 m_coast('patch','r');%红色填充 m_g ...

  7. Git创建本地仓库&把pycharm项目添加GitHub仓库上

    一.创建本地仓库 1.1.下载Git地址:https://git-scm.com/downloads 下载完,一路next就可以 1.2.打开Git Bash输入: #创建一个learngit目录 $ ...

  8. Git-flow 使用笔记

    git-flow 原理:A successful Git branching model,两篇不错的中文翻译: Git开发管理之道,一个成功的Git分支模型. 简单来说,git-flow 就是在 gi ...

  9. 【前端】CSS总结

    ========================   CSS层叠样式表======================== 命名规则:使用字母.数字或下划线和减号构成,不要以数字开头 一.css的语法-- ...

  10. 在线优化算法 FTRL 的原理与实现

    在线学习想要解决的问题 在线学习 ( \(\it{Online \;Learning}\) ) 代表了一系列机器学习算法,特点是每来一个样本就能训练,能够根据线上反馈数据,实时快速地进行模型调整,使得 ...