盘一盘 synchronized (一)—— 从打印Java对象头说起
Java对象头的组成
|--------------------------------------------------------------------------------------------------------------|
| Object Header (128 bits) |
|--------------------------------------------------------------------------------------------------------------|
| Mark Word (64 bits) | Klass Word (64 bits) |
|--------------------------------------------------------------------------------------------------------------|
| unused:25 | identity_hashcode:31 | unused:1 | age:4 | biased_lock:1 | lock:2 | OOP to metadata object | 无锁
|----------------------------------------------------------------------|--------|------------------------------|
| thread:54 | epoch:2 | unused:1 | age:4 | biased_lock:1 | lock:2 | OOP to metadata object | 偏向锁
|----------------------------------------------------------------------|--------|------------------------------|
| ptr_to_lock_record:62 | lock:2 | OOP to metadata object | 轻量锁
|----------------------------------------------------------------------|--------|------------------------------|
| ptr_to_heavyweight_monitor:62 | lock:2 | OOP to metadata object | 重量锁
|----------------------------------------------------------------------|--------|------------------------------|
| | lock:2 | OOP to metadata object | GC
|--------------------------------------------------------------------------------------------------------------|
使用JOL工具类,打印对象头
使用maven的方式,添加jol依赖
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.8</version>
</dependency>
创建一个对象A
public class A {
boolean flag = false;
}
使用jol工具类输出A对象的对象头
public static void main(String[] args){
A a = new A();
System.out.println(ClassLayout.parseInstance(a).toPrintable());
}
看看输出结果

偏向锁
public static void main(String[] args) throws InterruptedException {
Thread.sleep(5000);
A a = new A();
System.out.println(ClassLayout.parseInstance(a).toPrintable());
}
输出结果


public static void main(String[] args) throws InterruptedException {
Thread.sleep(5000);
A a = new A();
synchronized (a){
System.out.println(ClassLayout.parseInstance(a).toPrintable());
}
}
此时对象a,对象头内容有了明显的变化,当前偏向锁偏向主线程。

轻量级锁
public static void main(String[] args) throws Exception {
Thread.sleep(5000);
A a = new A();
Thread thread1= new Thread(){
@Override
public void run() {
synchronized (a){
System.out.println("thread1 locking");
out.println(ClassLayout.parseInstance(a).toPrintable()); //偏向锁
}
}
};
thread1.start();
thread1.join();
Thread.sleep(10000);
synchronized (a){
out.println("main locking");
out.println(ClassLayout.parseInstance(a).toPrintable());//轻量锁
}
}
thread1中依旧输出偏向锁,主线程获取对象A时,thread1虽然已经退出同步代码块,但主线程和thread1仍然为锁的交替竞争关系。故此时主线程输出结果为轻量级锁。
重量级锁
public static void main(String[] args) throws InterruptedException {
Thread.sleep(5000);
A a = new A();
Thread thread1 = new Thread(){
@Override
public void run() {
synchronized (a){
System.out.println("thread1 locking");
System.out.println(ClassLayout.parseInstance(a).toPrintable());
try {
//让线程晚点儿死亡,造成锁的竞争
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
Thread thread2 = new Thread(){
@Override
public void run() {
synchronized (a){
System.out.println("thread2 locking");
System.out.println(ClassLayout.parseInstance(a).toPrintable());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
thread1.start();
thread2.start();
}
thread1 和 thread2 同时竞争对象a,此时输出结果为重量级锁

盘一盘 synchronized (一)—— 从打印Java对象头说起的更多相关文章
- 并发王者课-青铜5:一探究竟-如何从synchronized理解Java对象头中的锁
在前面的文章<青铜4:synchronized用法初体验>中,我们已经提到锁的概念,并指出synchronized是锁机制的一种实现.可是,这么说未免太过抽象,你可能无法直观地理解锁究竟是 ...
- 015-线程同步-synchronized几种加锁方式、Java对象头和Monitor、Mutex Lock、JDK1.6对synchronized锁的优化实现
一.synchronized概述基本使用 为确保共享变量不会出现并发问题,通常会对修改共享变量的代码块用synchronized加锁,确保同一时刻只有一个线程在修改共享变量,从而避免并发问题. syn ...
- java对象头信息和三种锁的性能对比
java头的信息分析 首先为什么我要去研究java的对象头呢? 这里截取一张hotspot的源码当中的注释 这张图换成可读的表格如下 |-------------------------------- ...
- JAVA对象头详解(含32位虚拟机与64位虚拟机)
为什么要学习Java对象头 学习Java对象头主要是为了解synchronized底层原理,synchronized锁升级过程,Java并发编程等. JAVA对象头 由于Java面向对象的思想,在JV ...
- 探究java对象头
探究java对象头 研究java对象头,我这里先截取Hotspot中关于对象头的描述,本文研究基于64-bit HotSpot VM 文件路径 openjdk-jdk8u-jdk8u\hotspot\ ...
- JVM源码分析之Java对象头实现
原创申明:本文由公众号[猿灯塔]原创,转载请说明出处标注 “365篇原创计划”第十一篇. 今天呢!灯塔君跟大家讲: JVM源码分析之Java对象头实现 HotSpot虚拟机中,对象在内存中的布局分为三 ...
- jvm源码解析java对象头
认真学习过java的同学应该都知道,java对象由三个部分组成:对象头,实例数据,对齐填充,这三大部分扛起了java的大旗对象,实例数据其实就是我们对象中的数据,对齐填充是由于为了规则分配内存空间,j ...
- JAVA对象头
#为了防止自己忘记,先记着,之前我一直以为<深入理解JAVA虚拟机>写错了来着. 一. JAVA对象 在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头(Header ...
- Java对象头与锁
对象由多部分构成的,对象头,属性字段.补齐区域等.所谓补齐区域是指如果对象总大小不是4字节的整数倍,会填充上一段内存地址使之成为整数倍. 后面两个很好理解,今天我主要想总结一下对象头: 对象头这部分在 ...
随机推荐
- PHP调用语音合成接口
百度TTS 语音合成 //百度文件转换成语音 private function toSpeech($text) { define('DEMO_CURL_VERBOSE', false); $obj=[ ...
- 在.NET Core 3.0中的WPF中使用IOC图文教程
我们都知道.NET Core 3.0已经发布了第六个预览版,我们也知道.NET Core 3.0现在已经支持创建WPF项目了,刚好今天在写一个代码生成器的客户端的时候用到了WPF,所以就把WPF创建以 ...
- Java NIO学习系列二:Channel
上文总结了Java NIO中的Buffer相关知识点,本文中我们来总结一下它的好兄弟:Channel.上文有说到,Java NIO中的Buffer一般和Channel配对使用,NIO中的所有IO都起始 ...
- 【MYSQL】mysql大数据量分页性能优化
转载地址: http://www.cnblogs.com/lpfuture/p/5772055.html https://www.cnblogs.com/shiwenhu/p/5757250.html ...
- 32| 无实例无真相:基于LoadRunner实现企业级服务器端性能测试的实践(上)
- python之内置函数,匿名函数,递归函数
一. 内置函函数 什么是内置函数?就是Python给你提供的,拿来直接用的函数,比如print,input等等.截止到python版本3.6.2,现在python一共为我们提供了68个内置函数.它们就 ...
- python3下re模块的使用
**explain:**python3中的re库是一个正则匹配的函数库,里面包含了各种功能的正则函数,下面,我们一起学习下其中的几个常用函数 * **match()方法**: 从主串的起始位置开始匹配 ...
- SpringCloud系列——限流、熔断、降级
前言 分布式环境下,服务直接相互调用,一个复杂的业务可能要调用多个服务,例如A -> B -> C -> D,当某个服务出现异常(调用超时.调用失败等)将导致整个流程阻塞崩溃,严重的 ...
- MySQL数据库设计与开发规范
目录 1. 规范背景与目的 2. 设计规范 2.1. 数据库设计 2.1.1. 库名 2.1.2. 表结构 2.1.3. 列数据类型优化 2.1.4. 索引设计 2.1.5. 分库分表.分区表 2.1 ...
- c++稍微复杂桶排序(未完待续~)
由于上次的桶排序占用空间太多,这次又有了一个新的办法 直接上代码: #include <bits/stdc++.h> using namespace std; int n; void bu ...