简单了解synchronized

什么是synchronized

synchronized是Java提供的一个关键字,用于方法或者代码块,保证并发安全。

synchronized使用场景

同步代码块(原子性)

synchronized可以用在方法上,或者用在代码块。

可锁的对象可以是普通对象,或者是类(也就是Class对象)。

public class SynchronizedTest {static final Object monitor = new Object();public static void main(String[] args) {synchronized (monitor) {System.out.println("对象锁同步代码块访问");}synchronized (SynchronizedTest.class) {System.out.println("类锁同步代码块访问");}}
}

线程通信

线程交替打印1~100

public class SynchronizedTest {private static final Object monitor = new Object();private static volatile int count = 0;private static final int MAX = 100;public static void main(String[] args) {Thread t1 = new Thread(new Print(), "thread-1");Thread t2 = new Thread(new Print(), "thread-2");t1.start();t2.start();}static class Print implements Runnable {@Overridepublic void run() {while (count <= MAX) {synchronized (monitor) {try {if (count <= MAX) {System.out.println(Thread.currentThread().getName() + ": " + count);count++;}monitor.notify();monitor.wait();} catch (InterruptedException e) {throw new RuntimeException(e);}}}}}
}

synchronized原理

字节码层面

  • 同步代码块使用monitorenter和monitorexit实现
  • 同步方法使用ACC_SYNCHRONIZED实现

数据结构方面

和ReentrantLock有着类似的实现结构:

  • monitor:锁对象,有一个count计数器用来实现重入
  • value:互斥量
  • Owner:持有锁的线程
  • EntryList:同步队列,没有获取到锁的线程会在这里阻塞
  • WaitSet:条件队列,持有锁的线程调用了wait()之后会被放到条件队列,并唤醒同步队列的第一个阻塞节点

image-20240325185308438

synchronized锁升级

synchronized的锁有四种状态:无锁、偏向锁、轻量级锁、重量级锁

image-20240325191122481

对于没有锁定的对象,锁标志位是01,此时可能是无锁或者偏向锁状态,对于轻量级锁,锁标志位是00,对于重量级锁,锁标志位是10。

在JDK6以后引入了偏向锁以及轻量级锁来优化synchronized的性能,这才使得synchronized的性能和ReentrantLock的性能差不多。

轻量级锁

轻量级锁是为了只有两个线程来交替获取同一个锁的状况进行的优化,对于没有锁定的对象,会先在本线程的栈帧生成一个锁记录(Lock Record)的空间,用于拷贝当前的Mark Word,随后用CAS把Mark Word指向栈帧的指针指向本线程:

  • 如果成功了,则代表当前线程获取到该对象的锁,并且修改锁标志位为00。
  • 如果失败了,则说明至少有一条线程在争抢锁,先检查Mark Word当前指针是否指向本线程的栈帧,是则直接进入同步代码块执行,如果有多条线程争抢,则锁需要膨胀到重量级锁。

对于轻量级锁的释放,同样用到CAS操作,把栈帧的锁记录(Lock Record)替换回Mark Word:

  • 如果成功了,则说明同步过程完成
  • 如果失败了,也就是锁膨胀了,说明其它(第三个或者更多)线程尝试获取过该锁,需要唤醒其它线程

偏向锁

偏向锁是为了消除无竞争的情况下的一个锁优化,当线程获取一个无锁状态的对象,会先用CAS尝试修改Thread ID设置为自己的线程ID,如果设置成功,同时会把偏向锁标志位设置为1,此后的线程访问这个同步代码块将不用再执行同步操作。

当有其他线程尝试获取锁的时候,偏向锁失效,发生锁升级为轻量级锁,撤销偏向锁标志位为0,后续操作在轻量级锁已经叙述过。

重量级锁

利用操作系统进程通信信号量的互斥量来实现,锁标志位为10,在多线程竞争锁的时候,重量级锁更加合适,避免了线程空转占用CPU

synchronized锁优化

锁自旋

锁自旋(不断重试)代替锁阻塞(放弃CPU时间片,直接挂起)

锁消除

逃逸分析(锁的对象是本地变量,不会共享),某个代码块只会被单一线程访问

锁粗化

不要连续的加锁和解锁,适当加大锁的粒度可能效率更高,避免在循环次数很多的循环内部使用synchronized

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

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

相关文章

JQ操作Dom(下)

一、设置样式 <div>设置样式</div> <script type"text/javascript">//设置一条样式$(div).css(background-color,red);//设置多条样式使用类名的方式 </script> <div>设置样式 </div> <script type"text/javascript&q…

C++语法|C++八股|内存泄漏杂谈

文章目录 定义分类防⽌内存泄露的方法 定义 内存泄漏是指已分配的内存未能成功释放&#xff0c;并且程序失去了对该内存的控制&#xff0c;因此无法再次使用或释放。随着程序的运行&#xff0c;内存泄漏会逐渐积累&#xff0c;最终可能导致内存不足&#xff0c;影响程序的性能…

Spring Boot设置io临时目录

在部署springboot项目&#xff0c;使用MultipartFile上传文件会出现以下异常 Failed to parse multipart servlet request; nested exception is java.io.IOException: The temporary upload location [/tmp/tomcat.3016596448718765136.18001/work/Tomcat/localhost/xx] is …

【ZZULI数据结构实验一】多项式的三则运算

【ZZULI数据结构实验一】多项式的四则运算 ♋ 结构设计♋ 方法声明♋ 方法实现&#x1f407; 定义一个多项式类型并初始化---CreateDataList&#x1f407; 增加节点---Getnewnode&#x1f407; 打印多项式类型的数据-- PrintPoly&#x1f407; 单链表的尾插--Listpush_back&…

C++ 优先级与结合性

运算优先级和结合性 表达式有多种运算符混合使用时&#xff0c;求解表达式的值&#xff0c;首先要解决各种运算符的运算优先次序问题。即&#xff0c;优先级和结合性。 例如&#xff1a;下面表达式的值取决于5种运算符的优先次序。 优先级是指不同级别运算符之间的运算次序&am…

VC++ class wizard介绍

Visual C的集成开发环境向用户提供了一个功能很强的操作类的工具—ClassWizard&#xff0c;我们可以利用该工具非常方便地向应用程序中添加类、向类中添加消息处理函数、成员函数、以及添加成员变量等。 一 、ClassWizard简介 ClassWizard既可以操作由AppWizard在应用程序框架…

海量数据处理项目-账号微服务和流量包数据库表+索引规范(上)

海量数据处理项目-账号微服务和流量包数据库表索引规范&#xff08;上&#xff09; 第1集 账号微服务和流量包数据库表索引规范讲解《上》 简介&#xff1a;账号微服务和流量包数据库表索引规范讲解 短链平台大课难度层级曲线图&#xff1a;由浅入深 索引规范 主键索引名为…

卡行领航家用户端是怎么拼团怎么挣钱的?

#领航家代理政策/怎么代理/奖金制度/双2.0模式# 全国V&#xff1a;ok1234vip 领航家用户端&#xff1a;0.52费率 一次拼团0.44费率 两次拼团0.36费率 三次拼团0.2费率 ………… 十次拼团&#xff0c;客户每月挣20480 领航家代理端&#xff1a;无押激活返现高达166/台 分润万5-万…

Shell教程_不同Shell中管道操作符的差异

Shell教程_不同Shell中管道操作符的差异 不同的 Unix / Linux Shell (如 Bash, Zsh, Csh 和 Fish 等) 在语法方面存在一些差异, 主要是因为它们采用了不同的设计理念和语法规则。 这些差异在编写 Shell 脚本或在命令行中使用不同的 Shell 时可能会引起困惑和问题。 因此, 有…

P1383 高级打字机(可持续化线段树)

题目描述 早苗入手了最新的高级打字机。最新款自然有着与以往不同的功能&#xff0c;那就是它具备撤销功能&#xff0c;厉害吧。 请为这种高级打字机设计一个程序&#xff0c;支持如下 33 种操作&#xff1a; T x&#xff1a;Type 操作&#xff0c;表示在文章末尾打下一个小…

vue 中实现下载后端返回的流式数据

验证是否是blob /*** Event 验证是否为blob格式* */export async function blobValidate(data) {try {const text await data.text();JSON.parse(text);return false;} catch (error) {return true;}}get请求 /*** Event: get请求下载后端返回的数据流* description: url[Stri…

RockyLinux8 RockyLinux9安装postgresql16-devel开发包

1、PG的插件扩展有些需要自行编译&#xff0c;需要安装PG开发包 2、RockyLinux8安装 #创建用户先 useradd postgressudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-8-x86_64/pgdg-redhat-repo-latest.noarch.rpm sudo dnf -qy module disab…

计算机网络复试总结(五)

可能会问&#xff1a; 基础知识问题&#xff1a; 请简述TCP/IP协议栈的层次结构及其功能。 TCP/IP协议栈的层次结构及其功能可以简要概述如下&#xff1a; 层次结构&#xff1a; TCP/IP协议栈通常被划分为四个主要层次&#xff0c;从底层到高层分别是网络接口层&#xff08;也…

Flutter 旋转动画 线性变化的旋转动画

直接上代码 图片自己添加一张就好了 import dart:math;import package:flutter/material.dart;import package:flutter/animation.dart;void main() > runApp(MyApp()); //旋转动画 class MyApp extends StatelessWidget {overrideWidget build(BuildContext context) {re…

【python】正则表达式

文章目录 正则表达式对象re.RegexObjectre.MatchObject符号说明匹配基础匹配?=、?<=、?!、?<!字符类re模块编译正则表达式compile 函数匹配字符串re.matchre.searchre.findallre.finditer替换字符串re.sub分割字符串re.split正则表达式修饰符 - 可选标志主要用于网页…

ESCTF-逆向赛题WP

ESCTF_reverse题解 逆吧腻吧babypybabypolyreeasy_rere1你是个好孩子完结撒花 Q_W_Q 逆吧腻吧 下载副本后无壳&#xff0c;直接拖入ida分析分析函数逻辑&#xff1a;ida打开如下&#xff1a;提取出全局变量res的数据后&#xff0c;编写异或脚本进行解密&#xff1a; a[0xBF, …

Spring Task 知识点详解、案例、源代码解析

简介&#xff1a;Spring Task 定时任务   所谓定时任务。就是依据我们设定的时间定时运行任务&#xff0c;就像定时发邮件一样&#xff0c;设定时间到了。邮件就会自己主动发送。 在Spring大行其道的今天&#xff0c;Spring也提供了其定时任务功能&#xff0c;Spring Task。同…

【ARM64 常见汇编指令学习 22 -- ARMv8/v9 入栈寄存器介绍】

文章目录 ARMv8/v9 入栈寄存器介绍可以不入栈的寄存器需要入栈的寄存器&#xff08;被调用者保存的寄存器&#xff09;入栈顺序出栈顺序示例汇编代码 ARMv8/v9 入栈寄存器介绍 在 ARMv8 架构中&#xff0c;函数调用遵循一组称为 AAPCS64 &#xff08;ARMv8 64-bit Procedure C…

3.3 数据定义 数据库与系统概论

目录 3.3.1 模式的定义与删除 1. 定义模式 2. 删除模式 CASCADE&#xff08;级联&#xff09; RESTRICT&#xff08;限制&#xff09; 3.3.2 基本表的定义、删除与修改 表的定义 2.数据类型 3. 模式与表 4. 修改基本表 5. 删除基本表 3.3.3 索引的建立与删除 1. …

力扣刷题44-46(力扣0062/0152/0198)

62. 不同路径 题目描述&#xff1a; 一个机器人位于一个 m x n 网格的左上角 &#xff0c;机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角。问总共有多少条不同的路径&#xff1f; 思路&#xff1a; 其实就是问(0,0)->(m-1,n-1)一共有几条路。 第一个…