synchronized修饰方法和代码块底层实现有什么区别

首发2023-12-21 18:01·yuan人生 

synchronized修饰方法和代码块底层实现有什么区别-今日头条 (toutiao.com)

面试的时候经常有人问synchronized修饰方法和代码块底层实现有什么区别了,你来说下。实际做java开发很少有人关注这些东西,也基本没用。但面试就这样要能上天也能入地。那么我们从synchronized的字节码来看看两者到底有什么区别。

  1. synchronized代码块
public class SynchCode {public int num = 0;public void test(){synchronized (this){num++;}}
}

编译后使用javap查看字节码:

PS F:\workspace2\testShell\target\classes\com\test> javap -v -c -s -l SynchCode.class

Classfile /F:/workspace2/testShell/target/classes/com/test/SynchCode.class

Last modified 2023-12-21; size 491 bytes

MD5 checksum 016ede9c00699bbca1c9f55b94e782b4

Compiled from "SynchCode.java"

public class com.test.SynchCode

minor version: 0

major version: 55

flags: ACC_PUBLIC, ACC_SUPER

Constant pool:

#1 = Methodref #4.#19 // java/lang/Object."<init>":()V

#2 = Fieldref #3.#20 // com/test/SynchCode.num:I

#3 = Class #21 // com/test/SynchCode

#4 = Class #22 // java/lang/Object

#5 = Utf8 num

#6 = Utf8 I

#7 = Utf8 <init>

#8 = Utf8 ()V

#9 = Utf8 Code

#10 = Utf8 LineNumberTable

#11 = Utf8 LocalVariableTable

#12 = Utf8 this

#13 = Utf8 Lcom/test/SynchCode;

#14 = Utf8 test

#15 = Utf8 StackMapTable

#16 = Class #23 // java/lang/Throwable

#17 = Utf8 SourceFile

#18 = Utf8 SynchCode.java

#19 = NameAndType #7:#8 // "<init>":()V

#20 = NameAndType #5:#6 // num:I

#21 = Utf8 com/test/SynchCode

#22 = Utf8 java/lang/Object

#23 = Utf8 java/lang/Throwable

{

public int num;

descriptor: I

flags: ACC_PUBLIC

public com.test.SynchCode();

descriptor: ()V

flags: ACC_PUBLIC

Code:

stack=2, locals=1, args_size=1

0: aload_0

1: invokespecial #1 // Method java/lang/Object."<init>":()V

4: aload_0

5: iconst_0

6: putfield #2 // Field num:I

9: return

LineNumberTable:

line 3: 0

line 5: 4

LocalVariableTable:

Start Length Slot Name Signature

0 10 0 this Lcom/test/SynchCode;

public void test();

descriptor: ()V

flags: ACC_PUBLIC

Code:

stack=3, locals=3, args_size=1

0: aload_0

1: dup

2: astore_1

3: monitorenter

4: aload_0

5: dup

6: getfield #2 // Field num:I

9: iconst_1

10: iadd

11: putfield #2 // Field num:I

14: aload_1

15: monitorexit

16: goto 24

19: astore_2

20: aload_1

21: monitorexit

22: aload_2

23: athrow

24: return

Exception table:

from to target type

4 16 19 any

19 22 19 any

LineNumberTable:

line 8: 0

line 9: 4

line 10: 14

line 11: 24

LocalVariableTable:

Start Length Slot Name Signature

0 25 0 this Lcom/test/SynchCode;

StackMapTable: number_of_entries = 2

frame_type = 255 /* full_frame */

offset_delta = 19

locals = [ class com/test/SynchCode, class java/lang/Object ]

stack = [ class java/lang/Throwable ]

frame_type = 250 /* chop */

offset_delta = 4

}

SourceFile: "SynchCode.java"

可以看出JVM通过进入、退出监视器(Monitor)来实现。这里为什么两个monitorexit,就是防止synchronized代码块出现异常,监视器也能正常退出,不至于死锁。

  1. synchronized方法
public class SynchMethod1 {public int num = 0;public synchronized void test(){num++;}
}

编译后使用javap查看字节码:

PS F:\workspace2\testShell\target\classes\com\test> javap -v -c -s -l SynchMethod1.class

Classfile /F:/workspace2/testShell/target/classes/com/test/SynchMethod1.class

Last modified 2023-12-21; size 394 bytes

MD5 checksum bdb278f9435449b792a5b02c368690ab

Compiled from "SynchMethod1.java"

public class com.test.SynchMethod1

minor version: 0

major version: 55

flags: ACC_PUBLIC, ACC_SUPER

Constant pool:

#1 = Methodref #4.#17 // java/lang/Object."<init>":()V

#2 = Fieldref #3.#18 // com/test/SynchMethod1.num:I

#3 = Class #19 // com/test/SynchMethod1

#4 = Class #20 // java/lang/Object

#5 = Utf8 num

#6 = Utf8 I

#7 = Utf8 <init>

#8 = Utf8 ()V

#9 = Utf8 Code

#10 = Utf8 LineNumberTable

#11 = Utf8 LocalVariableTable

#12 = Utf8 this

#13 = Utf8 Lcom/test/SynchMethod1;

#14 = Utf8 test

#15 = Utf8 SourceFile

#16 = Utf8 SynchMethod1.java

#17 = NameAndType #7:#8 // "<init>":()V

#18 = NameAndType #5:#6 // num:I

#19 = Utf8 com/test/SynchMethod1

#20 = Utf8 java/lang/Object

{

public int num;

descriptor: I

flags: ACC_PUBLIC

public com.test.SynchMethod1();

descriptor: ()V

flags: ACC_PUBLIC

Code:

stack=2, locals=1, args_size=1

0: aload_0

1: invokespecial #1 // Method java/lang/Object."<init>":()V

4: aload_0

5: iconst_0

6: putfield #2 // Field num:I

9: return

LineNumberTable:

line 3: 0

line 5: 4

LocalVariableTable:

Start Length Slot Name Signature

0 10 0 this Lcom/test/SynchMethod1;

public synchronized void test();

descriptor: ()V

flags: ACC_PUBLIC, ACC_SYNCHRONIZED

Code:

stack=3, locals=1, args_size=1

0: aload_0

1: dup

2: getfield #2 // Field num:I

5: iconst_1

6: iadd

7: putfield #2 // Field num:I

10: return

LineNumberTable:

line 8: 0

line 9: 10

LocalVariableTable:

Start Length Slot Name Signature

0 11 0 this Lcom/test/SynchMethod1;

}

SourceFile: "SynchMethod1.java"

可以看到相对synchronized代码块没有了monitorenter、monitorexit监视器进入和退出。只是在方法的flags中用ACC_SYNCHRONIZED来修饰代表是同步方法。

  1. synchronized静态方法
public class SynchMethod2 {public static int num = 0;public static synchronized void test(){num++;}
}

编译后使用javap查看字节码:

PS F:\workspace2\testShell\target\classes\com\test> javap -v -c -s -l SynchMethod2.class

Classfile /F:/workspace2/testShell/target/classes/com/test/SynchMethod2.class

Last modified 2023-12-21; size 419 bytes

MD5 checksum 85dbad02fdde2b42c5c8296a7544883d

Compiled from "SynchMethod2.java"

public class com.test.SynchMethod2

minor version: 0

major version: 55

flags: ACC_PUBLIC, ACC_SUPER

Constant pool:

#1 = Methodref #4.#18 // java/lang/Object."<init>":()V

#2 = Fieldref #3.#19 // com/test/SynchMethod2.num:I

#3 = Class #20 // com/test/SynchMethod2

#4 = Class #21 // java/lang/Object

#5 = Utf8 num

#6 = Utf8 I

#7 = Utf8 <init>

#8 = Utf8 ()V

#9 = Utf8 Code

#10 = Utf8 LineNumberTable

#11 = Utf8 LocalVariableTable

#12 = Utf8 this

#13 = Utf8 Lcom/test/SynchMethod2;

#14 = Utf8 test

#15 = Utf8 <clinit>

#16 = Utf8 SourceFile

#17 = Utf8 SynchMethod2.java

#18 = NameAndType #7:#8 // "<init>":()V

#19 = NameAndType #5:#6 // num:I

#20 = Utf8 com/test/SynchMethod2

#21 = Utf8 java/lang/Object

{

public static int num;

descriptor: I

flags: ACC_PUBLIC, ACC_STATIC

public com.test.SynchMethod2();

descriptor: ()V

flags: ACC_PUBLIC

Code:

stack=1, locals=1, args_size=1

0: aload_0

1: invokespecial #1 // Method java/lang/Object."<init>":()V

4: return

LineNumberTable:

line 3: 0

LocalVariableTable:

Start Length Slot Name Signature

0 5 0 this Lcom/test/SynchMethod2;

public static synchronized void test();

descriptor: ()V

flags: ACC_PUBLIC, ACC_STATIC, ACC_SYNCHRONIZED

Code:

stack=2, locals=0, args_size=0

0: getstatic #2 // Field num:I

3: iconst_1

4: iadd

5: putstatic #2 // Field num:I

stack=1, locals=0, args_size=0

0: iconst_0

1: putstatic #2 // Field num:I

4: return

LineNumberTable:

line 5: 0

}

SourceFile: "SynchMethod2.java"

可以看到静态方法和非静态方法一样,只是在方法的flags中用ACC_SYNCHRONIZED来修饰代表是同步方法。

到这里,相信大家也该知道怎么回答该问题了。synchronized代码块底层字节码是用监视器monitorenter、monitorexit来实现的。synchronized修饰方法无论是静态方法还是非静态方法底层字节码都是在flags加了个ACC_SYNCHRONIZED来修饰代表是同步方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/236566.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Rocky Linux 9.3 安装 MinIO 最新版本 (超级详细版本)

安装步骤 MinIO官网文件目录 运行以下 curl 命令将 MinIO 的二进制文件下载到“ /usr/local/bin/minio ” curl -o /usr/local/bin/minio https://dl.min.io/server/minio/release/linux-amd64/minio 现在通过下面的 chmod 命令使 MinIO 二进制文件可执行 sudo chmod x /us…

Codeforces Round 916 (Div. 3)(A~E2)

A 统计一下每个字母的出现次数然后输出即可 #include <bits/stdc.h> #define rep(i,a,b) for(register int i (a); i < (b); i) #define fep(i,a,b) for(register int i (a); i > (b); --i) #define ls p<<1 #define rs p<<1|1 #define PII pair&l…

【深度学习】序列生成模型(四):评价方法

文章目录 一、困惑度&#xff08;Perplexity&#xff09;1. 定义2. 计算3. 衡量两个分布之间的差异4. 意义 二、BLEU&#xff08;Bilingual Evaluation Understudy&#xff09;1. 定义2. 意义3. 实例 三、ROUGE&#xff08;Recall-Oriented Understudy for Gisting Evaluation&…

linux 内核经典RCU

如果不关心使用的RCU是不可抢占RCU还是可抢占RCU&#xff0c;应该使用经典RCU的编程接口。最初的经典RCU是不可抢占RCU&#xff0c;后来实现了可抢占RCU&#xff0c;经典RCU的意思发生了变化&#xff1a;如果内核编译了可抢占RCU&#xff0c;那么经典RCU的编程接口被实现为可抢…

分布式全局ID之雪花算法

系列文章目录 提示&#xff1a;这里可以添加系列文章的所有文章的目录&#xff0c;目录需要自己手动添加 雪花算法 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 系列文章目录前言一、什么是雪花算法&#xff1f…

Kafka--Kafka日志索引详解以及生产常见问题分析与总结

一、Kafka的Log日志梳理 ​ 这一部分数据主要包含当前Broker节点的消息数据(在Kafka中称为Log日志)。这是一部分无状态的数据&#xff0c;也就是说每个Kafka的Broker节点都是以相同的逻辑运行。这种无状态的服务设计让Kafka集群能够比较容易的进行水平扩展。比如你需要用一个新…

嵌入式开发工程师

嵌入式开发 岗位需求 上岗必备 文章目录 嵌入式开发前言一、负责新产品的电路图、PCB、嵌入式程序、软硬件调试等工作二、负责对现有产品进行硬件优化、调试、维护、排故等工作三、 负责各种单片机,传感器,元器件选型以及BOM表整理四、 负责硬件产品研发和量产过程中项目设计…

网络技术基础与计算思维实验教程_3.1_单BSS实验(基本服务集合实验)

无线局域网的最小基本组件是基本服务BSS 实验内容 实验目的 实验原理 实验步骤 为了显示AP的有效通信范围 切换到物理工作区 把物理工作区导航到城市家园 直接在城市家园放置AP0 可以看到AP0的通信范围 放置笔记本电脑 在默认情况下 笔记本电脑上 安装了以太网卡 现在换成无…

大模型之二十一-小语言模型塞道开启

当前提到大语言模型&#xff0c;大家想到的都是动辄百亿规模以上参数量的模型&#xff0c;13B、70B都是稀疏平常入门级的&#xff0c;但是目前从模型层面来看&#xff0c;模型参数量的规模两极分化已经来临&#xff0c;早期各大公司为了效果怼上去&#xff0c;采取了简单粗暴的…

[Angular] 笔记 4:ngFor

ngFor 是一个 for 循环&#xff0c;只能用于循环遍历 list&#xff0c;不能用于遍历单个实体。 下图中的 pokemons 通常是数据库中的数据&#xff1a; 例子&#xff1a; app.components.ts: // 使用类型检查 interface Pokemon {id: number;name: string;type: string;// is…

c++学习:static在类中的空间分配+实战+单例设计模式

目录 情况一&#xff1a; 证实方法&#xff1a; 结果&#xff1a; 情况二&#xff1a; 证实方法&#xff1a; 结果&#xff1a; 实战1&#xff1a;在同一个类中不同对象中传递消息 方法一&#xff1a; 方法二&#xff1a; 实战2&#xff1a;该类只用创建一次&#xff0…

【postgresql】PSQLException: An I/O error occurred while sending to the backend.

org.postgresql.util.PSQLException: An I/O error occurred while sending to the backend. 发送到后端时发生I/O错误。 java.io.IOException: Tried to send an out-of-range integer as a 2-byte value: 34284 尝试将超出范围的整数作为2字节值发送&#xff1a;34284 pos…

C++学习——访问限定符

在C中&#xff0c;protected, friend, 和 public 是访问限定符&#xff0c;用于指定类成员的访问级别。 访问限定符 public public 成员可以从类的任何地方访问&#xff0c;包括类的外部。这通常是你希望外部代码能够直接访问和操作的那些方法和属性。比如&#xff0c;一个类…

OpenHarmony开发环境快速搭建(无需命令行)

一. 搭建Windows环境 在嵌入式开发中&#xff0c;很多开发者习惯于使用Windows进行代码的编辑&#xff0c;比如使用Windows的Visual Studio Code进行OpenHarmony代码的开发。但当前阶段&#xff0c;大部分的开发板源码还不支持在Windows环境下进行编译&#xff0c;如Hi3861、H…

LLM微调(四)| 微调Llama 2实现Text-to-SQL,并使用LlamaIndex在数据库上进行推理

Llama 2是开源LLM发展的一个巨大里程碑。最大模型及其经过微调的变体位居Hugging Face Open LLM排行榜&#xff08;https://huggingface.co/spaces/HuggingFaceH4/open_llm_leaderboard&#xff09;前列。多个基准测试表明&#xff0c;就性能而言&#xff0c;它正在接近GPT-3.5…

助老理发,寒冬送暖从头开始

为进一步弘扬尊老、敬老、爱老、助老的中华民族传统美德&#xff0c;解决老年人年龄大、冬季出行不便的问题&#xff0c;2023年12月20日&#xff0c;绿萝志愿服务队在翠堤社区开展了“助老理发”志愿活动。 大雪过后天气格外寒冷&#xff0c;但志愿者们依旧早早的来现场做…

【Flink-Bug】Flink 自定义 Sink 重写 RichSinkFunction 方法时重复调用 open 的解决方案

【Flink-Bug】Flink 自定义 Sink 重写 RichSinkFunction 方法时重复调用 open 的解决方案 Flink 自定义 RichinkFunction 时可能会重写 open 方法进行某些连接的初始化操作&#xff0c;但是会出现重复调用 open 方法的问题&#xff0c;如&#xff1a;MQ&#xff0c;如果重复调用…

【Unity实现海浪盒_GerstnerWaves算法_焦散Caustics效果_案例分享】

Unity实现海浪盒效果 背景设置好顶点色参数海浪盒水体部分效果为了快速实现效果,下面用Shadergraph实现效果。ShaderGraph水体全节点ShaderGraph全节点模块序号ShaderGraph属性ShaderGraph Graph Setting1. GerstnerWave 顶点动画部分,输出的是顶点偏移和NormalOSWaves算法Ge…

扭蛋机小程序搭建,“互联网+”下的发展优势

随着我国生活水平和消费能力不断提高&#xff0c;人们对各种潮流文化类的产品需求也快速上升。至此&#xff0c;我国潮流文化市场得到了快速发展&#xff01; 扭蛋机作为潮玩中的一种商业模式&#xff0c;深受不同年龄层用户的喜爱。并且扭蛋机的种类也是各式各样&#xff0c;…

MYSQL单表删除重复的数据方法

先简述遇到的问题&#xff1a;我要删除一张表的数据&#xff0c;先是查询到所有的重复的数据id直接进行删除操作&#xff0c;但是一直执行不完&#xff08;一直执行就是删除不完&#xff09; DELETE FROM table WHERE id IN ( SELECT MAX(id) id from table where rId…