当前位置: 首页 > news >正文

并发编程-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提供的一个关键字&#xff0c;Synchronized可以保证并发程序的原子性&#xff0c;可见性&#xff0c;有序性。 我们会把synchronized称为重量级锁。主要原因&#xff0c;是因为JDK1.6之前&#xff0c;synchronized是一个重量级锁相比于J…...

C语言——从头开始——深入理解指针(1)

一.内存和地址 我们知道计算上CPU&#xff08;中央处理器&#xff09;在处理数据的时候&#xff0c;是通过地址总线把需要的数据从内存中读取的&#xff0c;后通过数据总线把处理后的数据放回内存中。如下图所示&#xff1a; 计算机把内存划分为⼀个个的内存单元&#xff0c;每…...

微信小程序-绑定数据并在后台获取它

如图 遍历列表的过程中需要绑定数据&#xff0c;点击时候需要绑定数据 这里是源代码 <block wx:for"{{productList}}" wx:key"productId"><view class"product-item" bindtap"handleProductClick" data-product-id"{{i…...

【删除数组用delete和Vue.delete有什么区别】

删除数组用delete和Vue.delete有什么区别&#xff1f; 在 JavaScript 中&#xff0c;delete 和 Vue.js 中的 Vue.delete 是两个完全不同的概念&#xff0c;它们在删除数组元素时的作用和效果也有所不同。 JavaScript 中的 delete 关键字&#xff1a; 在原生 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&#xff0c;对过程进行简单记录。 步骤 ①安装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结构&#xff0c;后端采用主流的Springboot框架进行开发&#xff0c;前端采用主流的Vue.js进行开发。 整个平台包括前台和后台两个部分。 前台功能包括&#xff1a;首页、家政详情、家政入驻、用户中心模块。后台功能包括&#xff1a;家政管理、分类管理…...

C语言前世今生

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

android aidl进程间通信封装通用实现-用法说明

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

【Java中23种设计模式-单例模式2--懒汉式线程不安全】

加油&#xff0c;新时代打工人&#xff01; 今天&#xff0c;重新回顾一下设计模式&#xff0c;我们一起变强&#xff0c;变秃。哈哈。 23种设计模式定义介绍 Java中23种设计模式-单例模式 package mode;/*** author wenhao* date 2024/02/19 09:16* description 单例模式--懒…...

【后端高频面试题--Linux篇】

&#x1f680; 作者 &#xff1a;“码上有前” &#x1f680; 文章简介 &#xff1a;后端高频面试题 &#x1f680; 欢迎小伙伴们 点赞&#x1f44d;、收藏⭐、留言&#x1f4ac; 后端高频面试题--Linux篇 往期精彩内容Windows和Linux的区别&#xff1f;Unix和Linux有什么区别…...

网络原理HTTP/HTTPS(2)

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

【Java中23种设计模式-单例模式2--懒汉式2线程安全】

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

由LeetCode541引发的java数组和字符串的转换问题

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

HTTP 头部- Origin Referer

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

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 关键字用来声明变量&#xff0c;使用 let 声明的…...

动态DP入门线性动态DP

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

基于python+django+vue.js开发的停车管理系统

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

网站管理新利器:免费在线生成 robots.txt 文件!

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

【Java程序员面试专栏 Java领域】Java虚拟机 核心面试指引

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

洛谷C++简单题小练习day15—计算阶乘小程序(不用循环)

day15--计算阶乘小程序--2.19 习题概述 题目描述 求 n!&#xff0c;也就是 123⋯n。 挑战&#xff1a;尝试不使用循环语句&#xff08;for、while&#xff09;完成这个任务。 输入格式 第一行输入一个正整数 n。 输出格式 输出一个正整数&#xff0c;表示 n! 代码部分 …...

Vue报错,xxx is defined #变量未定义

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

Idea启动Gradle报错: Please, re-import the Gradle project and try again

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

Python函数(一)

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

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 网关是指一个位于微服务架构中的代理服务器&#xff0c;它负责将外部请求路由到内部微服务。API 网关可以提供多种功能&#xff0c;包括&#xff1a; 路由: 将请求路由到特定的微服务。负载均衡: 将请求分散到多个微服务实例上。安全: 身份验证、授权和安全策…...

stm32学习笔记-STLINK使用

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

Linux CentOS stream 9 firewalld

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

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…...