并发编程-Synchronized
什么是Synchronized
synchronized是Java提供的一个关键字,Synchronized可以保证并发程序的原子性,可见性,有序性。
我们会把synchronized称为重量级锁。主要原因,是因为JDK1.6之前,synchronized是一个重量级锁相比于JUC的锁显得非常笨重,存在性能问题。JDK1.6及之后,Java对synchronized进行的了一系列优化,性能与JUC的锁不相上下。
Synchronized 使用
synchronized可以修饰方法和代码块
方法:可修饰静态方法和非静态方法
代码块:同步代码块的锁对象可以为当前实例对象、字节码对象(class)、其他实例对象
1 修饰方法普通方法
synchronized修饰普通方法,锁对象默认为this
2 修饰静态方法
锁对象为Class对象
3 代码块
synchronized (lockobj) {// 书写同步代码
}
Synchronized原理分析
public class Demo {Object lock = new Object();public synchronized void demo() {}public void execute() {synchronized (lock) {System.out.println("get lock");}}
}
javac Demo.java
javap -c Demo.class
public synchronized void syncMethod();Code:0: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;3: ldc #5 // String get lock5: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V8: returnpublic void executeMethod();Code:0: aload_01: getfield #3 // Field lock:Ljava/lang/Object;4: dup5: astore_16: monitorenter7: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;10: ldc #5 // String get lock12: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V15: aload_116: monitorexit17: goto 2520: astore_221: aload_122: monitorexit23: aload_224: athrow25: return
从上述字节码指令看的到,同步代码块和同步方法的字节码是不同的:
对于synchronized同步块
,对应的monitorenter和monitorexit指令分别对应synchronized同步块的进入和退出。
为什么会多一个monitorexit?编译器会为同步块添加一个隐式的try-finally,在finally中会调用monitorexit命令释放锁
对于synchronized方法
,对应ACC_SYNCHRONIZED关键字,JVM进行方法调用时,发现调用的方
法被ACC_SYNCHRONIZED修饰,则会先尝试获得锁,方法调用结束了释放锁。在JVM底层,对于这两种synchronized的实现大致相同。都是基于monitorenter和monitorexit指令实现,底层还是使用 标记字段MarkWord和Monitor(管程)来实现重量级锁。
什么是管程?
Monitor中文翻译为管程,也有人称之为“监视器”,管程指的是管理共享变量以及对共享变量的操作过程,让他们支持并发。
Java中的所有对象都可以作为锁,每个对象都与一个 monitor 相关联,线程可以对 monitor 执行lock 和 unlock 操作。
Java并没有把lock和unlock操作直接开放给用户使用,但是却提供了两个指令来隐式地使用这两个操作:moniterenter和moniterexit。moniterenter对应lock操作,moniterexit对应unlock操作,通过这两个指锁定和解锁 monitor 对象来实现同步。
当一个monitor对象被线程持有后,它将处于锁定状态。对于一个 monitor 而言,同时只能有一个线程能锁定monitor,其它线程试图获得已被锁定的 monitor时,都将被阻塞。当monitor被释放后,阻塞中的线程会尝试获得该 monitor锁。一个线程可以对一个 monitor 反复执行 lock 操作,对应的释放锁时,需要执行相同次数的 unlock 操作。
管程相关文档:
https://www.cnblogs.com/binarylei/p/12544002.html#2-%E7%AE%A1%E7%A8%8Bmonitor
Synchronized锁升级
在JDK1.6之后同步锁一共有四种状态,级别从低到高依次是:无锁,偏向锁,轻量级锁,重量级锁。这四种状态
会随着竞争激烈情况逐渐升级。
偏向锁(需要运行时间在5-6s以上JVM才会开启)
只有一个线程访问锁资源(无竞争)的话,偏向锁就会把整个同步措施都消除,并记录当前持有锁资源的线程和锁的型。
轻量级锁
轻量级锁是基于这样一个想法:只有两个线程交替运行时,如果线程竞争锁失败了,先不立即挂起,而是让它飞一会儿(自旋),在等待过程中,可能锁就被释放了,这时该线程就可以重新尝试获取锁,同时记录持有锁资源的线程和锁的类型。
有关锁的信息都是object对象头中markdown来保存的
锁升级过程演示:
对象头怎么看每一位的含义可以看这篇博客
public class Demo {public static void main(String[] args) throws InterruptedException {// 为了开启偏向锁Thread.sleep(5001);Object lock = new Object();// 偏向锁 110printObj(lock, 1);// 都在main线程里面所以还是偏向锁synchronized (lock) {printObj(lock, 2);}// 再开一个线程进行资源争抢new Thread(() -> {synchronized (lock) {System.out.println("get lock one");// 升级成为了轻量级锁 00printObj(lock, 3);try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}).start();// 再开一个线程进行资源争抢new Thread(() -> {synchronized (lock) {System.out.println("get lock two");}}).start();// 少量竞争轻量级锁 00printObj(lock, 4);// 让上面的线程结束 然后开始疯狂竞争// 竞争非常的激烈会升级成重量级锁 10Thread.sleep(2000);for (int i = 0; i < 10; i ++) {new Thread(() -> {synchronized (lock) {try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("get lock three");}}).start();}printObj(lock, 5);}static void printObj(Object o, int i) {String s = ClassLayout.parseInstance(o).toPrintable();System.out.println(s + " " + i);}
}
java.lang.Object object internals:OFFSET SIZE TYPE DESCRIPTION VALUE0 4 (object header) 05 00 00 00 (00000101 00000000 00000000 00000000) (5)4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)8 4 (object header) e5 01 00 f8 (11100101 00000001 00000000 11111000) (-134217243)12 4 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total1
java.lang.Object object internals:OFFSET SIZE TYPE DESCRIPTION VALUE0 4 (object header) 05 d8 aa 05 (00000101 11011000 10101010 00000101) (95082501)4 4 (object header) e4 01 00 00 (11100100 00000001 00000000 00000000) (484)8 4 (object header) e5 01 00 f8 (11100101 00000001 00000000 11111000) (-134217243)12 4 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total2
get lock one
java.lang.Object object internals:OFFSET SIZE TYPE DESCRIPTION VALUE0 4 (object header) c8 ed 5f ad (11001000 11101101 01011111 10101101) (-1386222136)4 4 (object header) b5 00 00 00 (10110101 00000000 00000000 00000000) (181)8 4 (object header) e5 01 00 f8 (11100101 00000001 00000000 11111000) (-134217243)12 4 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total3
java.lang.Object object internals:OFFSET SIZE TYPE DESCRIPTION VALUE0 4 (object header) c8 ed 5f ad (11001000 11101101 01011111 10101101) (-1386222136)4 4 (object header) b5 00 00 00 (10110101 00000000 00000000 00000000) (181)8 4 (object header) e5 01 00 f8 (11100101 00000001 00000000 11111000) (-134217243)12 4 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total4
get lock two
java.lang.Object object internals:OFFSET SIZE TYPE DESCRIPTION VALUE0 4 (object header) ba 71 b5 05 (10111010 01110001 10110101 00000101) (95777210)4 4 (object header) e4 01 00 00 (11100100 00000001 00000000 00000000) (484)8 4 (object header) e5 01 00 f8 (11100101 00000001 00000000 11111000) (-134217243)12 4 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total5
相关文章:

并发编程-Synchronized
什么是Synchronized synchronized是Java提供的一个关键字,Synchronized可以保证并发程序的原子性,可见性,有序性。 我们会把synchronized称为重量级锁。主要原因,是因为JDK1.6之前,synchronized是一个重量级锁相比于J…...

C语言——从头开始——深入理解指针(1)
一.内存和地址 我们知道计算上CPU(中央处理器)在处理数据的时候,是通过地址总线把需要的数据从内存中读取的,后通过数据总线把处理后的数据放回内存中。如下图所示: 计算机把内存划分为⼀个个的内存单元,每…...

微信小程序-绑定数据并在后台获取它
如图 遍历列表的过程中需要绑定数据,点击时候需要绑定数据 这里是源代码 <block wx:for"{{productList}}" wx:key"productId"><view class"product-item" bindtap"handleProductClick" data-product-id"{{i…...

【删除数组用delete和Vue.delete有什么区别】
删除数组用delete和Vue.delete有什么区别? 在 JavaScript 中,delete 和 Vue.js 中的 Vue.delete 是两个完全不同的概念,它们在删除数组元素时的作用和效果也有所不同。 JavaScript 中的 delete 关键字: 在原生 JavaScript 中&a…...

【QT+QGIS跨平台编译】之四十二:【QWT+Qt跨平台编译】(一套代码、一套框架,跨平台编译)
文章目录 一、QWT介绍二、QWT下载三、文件分析四、pro文件五、编译实践5.1 Windows下编译4.2 Linux下编译5.3 MacOS下编译一、QWT介绍 QWT是一个基于Qt框架的开源C++库,用于创建交互式的图形用户界面。它提供了丰富的绘图和交互功能,可以用于快速开发图形化应用程序。 QWT包…...

yum方式快速安装mysql
问题描述 使用yum的方式简单安装了一下mysql,对过程进行简单记录。 步骤 ①安装wget和vim sudo yum -y install wget vim②下载mysql的rpm包 sudo wget https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm③升级和更新rpm包 sudo rpm -Uv…...

基于Java的家政预约管理平台
功能介绍 平台采用B/S结构,后端采用主流的Springboot框架进行开发,前端采用主流的Vue.js进行开发。 整个平台包括前台和后台两个部分。 前台功能包括:首页、家政详情、家政入驻、用户中心模块。后台功能包括:家政管理、分类管理…...

C语言前世今生
C语言前世今生 C语言的发展历史 C语言于1972年11月问世,1978年美国电话电报公司(AT&T)贝尔实验室正式发布C语言,1983年由美国国家标准局(American National Standards Institute,简称ANSI)…...

android aidl进程间通信封装通用实现-用法说明
接上一篇:android aidl进程间通信封装通用实现-CSDN博客 该aar包的使用还是比较方便的 一先看客户端 1 初始化 JsonProtocolManager.getInstance().init(mContext, "com.autoaidl.jsonprotocol"); //客户端监听事件实现 JsonProtocolManager.getInsta…...

【Java中23种设计模式-单例模式2--懒汉式线程不安全】
加油,新时代打工人! 今天,重新回顾一下设计模式,我们一起变强,变秃。哈哈。 23种设计模式定义介绍 Java中23种设计模式-单例模式 package mode;/*** author wenhao* date 2024/02/19 09:16* description 单例模式--懒…...

【后端高频面试题--Linux篇】
🚀 作者 :“码上有前” 🚀 文章简介 :后端高频面试题 🚀 欢迎小伙伴们 点赞👍、收藏⭐、留言💬 后端高频面试题--Linux篇 往期精彩内容Windows和Linux的区别?Unix和Linux有什么区别…...

网络原理HTTP/HTTPS(2)
文章目录 HTTP响应状态码200 OK3xx 表示重定向4xx5xx状态码小结 HTTPSHTTPS的加密对称加密非对称加密 HTTP响应状态码 状态码表⽰访问⼀个⻚⾯的结果.(是访问成功,还是失败,还是其他的⼀些情况…).以下为常见的状态码. 200 OK 这是⼀个最常⻅的状态码,表⽰访问成功 2xx都表示…...

【Java中23种设计模式-单例模式2--懒汉式2线程安全】
加油,新时代打工人! 简单粗暴,学习Java设计模式。 23种设计模式定义介绍 Java中23种设计模式-单例模式 Java中23种设计模式-单例模式2–懒汉式线程不安全 package mode;/*** author wenhao* date 2024/02/19 09:38* description 单例模式…...

由LeetCode541引发的java数组和字符串的转换问题
起因是今天在刷下面这个力扣题时的一个报错 541. 反转字符串 II - 力扣(LeetCode) 这个题目本身是比较简单的,所以就不讲具体思路了。问题出在最后方法的返回值处,要将字符数组转化为字符串,第一次写的时候也没思考直…...

HTTP 头部- Origin Referer
Origin & Referer Origin Header 示例 Origin 请求头部是一个 HTTP 头部,它提供了发起请求的网页的源(协议、域名和端口)信息。它通常在进行跨域资源共享(CORS)请求时使用,以便服务器可以决定是否接受…...

Python 实现Excel 文件合并
Excel 文件合并方法较多,前面文章有通过Uipath RPA 对文件进行合并,也可以通过Python或VBA写脚本合并。 通常写脚本维护性更加简洁,本文提供Python 脚本对Excel 文件进行合并,参考Uipath 调用Python 文章,Uipath 调用Python 脚本程序详解-CSDN博客 便能快速实现。代码如…...

ECMAScript 6+ 新特性 ( 一 )
2.1.let关键字 为了解决之前版本中 var 关键字存在存在着越域, 重复声明等多种问题, 在 ES6 以后推出 let 这个新的关键字用来定义变量 //声明变量 let a; let b,c,d; let e 100; let f 123, g hello javascript, h [];let 关键字用来声明变量,使用 let 声明的…...

动态DP入门线性动态DP
动态DP入门&线性动态DP 前言核心思想例1例22024牛客寒假4K2022牛客寒假2J结论 前言 OI-WiKi上有一个动态DP讲解,直接讲到了树型DP领域,同时需要树链剖分,门槛有点高。本文针对线性DP做一个动态DP的讲解。 首先当然要懂得一定的DP的相关…...

基于python+django+vue.js开发的停车管理系统
功能介绍 平台采用B/S结构,后端采用主流的Python语言进行开发,前端采用主流的Vue.js进行开发。 功能包括:车位管理、会员管理、停车场管理、违规管理、用户管理、日志管理、系统信息模块。 源码地址 https://github.com/geeeeeeeek/pytho…...

网站管理新利器:免费在线生成 robots.txt 文件!
🤖 探索网站管理新利器:免费在线生成 robots.txt 文件! 你是否曾为搜索引擎爬虫而烦恼?现在,我们推出全新的在线 robots.txt 文件生成工具,让你轻松管理网站爬虫访问权限,提升网站的可搜索性和…...

【Java程序员面试专栏 Java领域】Java虚拟机 核心面试指引
关于Java 虚拟机部分的核心知识进行一网打尽,主要包括Java虚拟机的内存分区,执行流程等,通过一篇文章串联面试重点,并且帮助加强日常基础知识的理解,全局思维导图如下所示 JVM 程序执行流程 包括Java程序的完整执行流程,以及Javac编译,JIT即时编译 Java程序的完整执…...

洛谷C++简单题小练习day15—计算阶乘小程序(不用循环)
day15--计算阶乘小程序--2.19 习题概述 题目描述 求 n!,也就是 123⋯n。 挑战:尝试不使用循环语句(for、while)完成这个任务。 输入格式 第一行输入一个正整数 n。 输出格式 输出一个正整数,表示 n! 代码部分 …...

Vue报错,xxx is defined #变量未定义
vue.js:5129 [Vue warn]: Error in v-on handler: "ReferenceError: count is not defined" 浏览器将这个变量 当做全局变量了,事实上它只是实例中的变量 加上this指定,是vue实例中的变量...

Idea启动Gradle报错: Please, re-import the Gradle project and try again
Idea启动Gradle报错:Warning:Unable to make the module: reading, related gradle configuration was not found. Please, re-import the Gradle project and try again. 解决办法: 开启步骤:View -> Tool Windows -> Gradle 点击refe…...

Python函数(一)
目录 一、定义函数 (一)向函数传递信息 (二)实参和形参 二、传递实参 (一)位置实参 (二)关键字实参 (三)默认值 (四)等效的函…...

Excel表的内容批量生成个人加水印的Word文档
Excel表的内容批量生成个人加水印的Word文档 以下代码可以直接复制到docm文件里使用 Sub 宏1()Dim MyDialog As FileDialogDim GetStr As String, Adoc As StringDim PsDoc As DocumentApplication.ScreenUpdating FalseSet MyDialog Application.FileDialog(msoFileDialogF…...

微服务设计:Spring Cloud API 网关概述
Spring Cloud API 网关是指一个位于微服务架构中的代理服务器,它负责将外部请求路由到内部微服务。API 网关可以提供多种功能,包括: 路由: 将请求路由到特定的微服务。负载均衡: 将请求分散到多个微服务实例上。安全: 身份验证、授权和安全策…...

stm32学习笔记-STLINK使用
stm32学习笔记-STLINK使用 使用ST-LINK调试程序进度表格 使用ST-LINK调试程序 说明 组成 总结 记录使用STLINK进行项目的烧写和调试,旨在高效的进行代码调试学习工具包括笔记本、keil5MDK、stm32f030c8t6电表主机、STLINK V2、导线、电表代码总的来说࿰…...

Linux CentOS stream 9 firewalld
随着互联网行业快速发展,服务器成为用户部署网络业务重要的网络工具,但随之而来的就是更密集的网络攻击,这给网站带来了很大的阻碍。防火墙作为保障网络安全的主要设备,可以很好的抵御网络攻击。 防火墙基本上使用硬件和软件两种…...

VLM多模态图像识别小模型UForm
参考:https://github.com/unum-cloud/uform https://huggingface.co/unum-cloud/uform-gen2-qwen-500m https://baijiahao.baidu.com/s?id=1787054120353641459&wfr=spider&for=pc demo:https://huggingface.co/spaces/unum-cloud/uform-gen2-qwen-500m-demo UF…...