先来看个奇怪的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. thinkphp 路径 (纯转)

    TP中有不少路径的便捷使用方法,比如模板中使用的__URL__,__ACTION__等,如果你对这些路径不是很明白,用起来说不定就会有这样或那样的问题,抑或出了错也不知道怎么改,现在我们看一下这些路径 ...

  2. imread()用法|| root权限

    1.ushort用法? USHORT is a macro which is not part of the official C++ language (it's probably defined ...

  3. TensorFlow 多 GPU 处理并行数据

    Multi-GPU processing with data parallelism If you write your software in a language like C++ for a s ...

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

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

  5. sql 模块sqllit

    1.创建数据库表 面对 SQLite 数据库,我们之前熟悉的 SQL 指令都可以用: >>> create_table = "create table books (tit ...

  6. Redis启动出现creating server tcp listening socket错误

    错误如图所示 解决方法 在命令行中运行 redis-cli.exe 127.0.0.1:6379>shutdown not connected>exit 然后重新运行redis-serve ...

  7. RecyclerView 的简单使用

    自从 Android 5.0 之后,google 推出了一个 RecyclerView 控件,他是 support-v7 包中的新组件,是一个强大的滑动组件,与经典的 ListView 相比,同样拥有 ...

  8. Unix 下 使用 RVM 管理 Ruby 和 gem

    转载:http://www.ibm.com/developerworks/cn/aix/library/au-aix-manage-ruby/   尽管 Internet Relay Chat.论坛和 ...

  9. A - Investment

    A - Investment John never knew he had a grand-uncle, until he received the notary's letter. He learn ...

  10. Otb_000_ElementUI 的 Drawer组件无法上下滚动没有滚动条

    场景:当导航为侧边栏的时候,鼠标滚轮滑动的时候,以及移动端,均不可上下拖动,如果展开全部将影响操作. 解决办法: /*1.显示滚动条:当内容超出容器的时候,可以拖动:*/ .el-drawer__bo ...