精心修炼Java并发编程(JUC)-volatile与synchronized关键字
volatile
volatile 是 JVM 提供的 最轻量级的同步机制,中文意思是不稳定的,易变的,用 volatile 修饰变量是为了保证变量在多线程中的可见性,它表达的含义是:告诉编译器,对这个变量的读写,需要基于主内存保证多CPU的缓存一致性。
volatile 变量的两个特性:解决可见性和有序性
1、解决可见性
保证变量对所有线程的可见性:当一条线程修改了 volatile 变量的值,新值对于其他线程来说是可以立即得知的。而普通变量不能做到这一点
线程写 volatile 变量的过程:
- 改变线程工作内存中 volatile 变量副本的值
- 将改变后的副本的值立即从工作内存刷新到主内存
线程读 volatile 变量的过程:
- 从主内存中读取 volatile 变量的最新值到线程的工作内存中
- 从工作内存中读取 volatile 变量的副本
注意:
1、volatile并不能保证并发操作的原子性,即不保证线程安全
2、volatile修饰引用类型,它只能保证引用本身的可见性,不能保证所引用对象内部属性的可见性
2、解决有序性
禁止进行指令重排序,具体一点解释,禁止重排序的规则如下:
- 写
volatile变量时,可以确保volatile写之前的操作不会被编译器重排序到volatile写之后。 - 读
volatile变量时,可以确保volatile读之后的操作不会被编译器重排序到volatile读之前。
synchronized
如果某一个资源被多个线程共享,为了避免因为资源抢占导致资源数据错乱,我们需要对线程进行同步,那么synchronized就是实现线程同步的关键字
synchronized的作用是保证在同一时刻, 被修饰的代码块或方法只会有一个线程执行,以达到保证并发安全的效果。
其用法如下:
从语法上讲,Synchronized可以把任何一个非null对象作为"锁",在HotSpot JVM实现中,锁有个专门的名字:对象监视器(Object Monitor)。
// (1)修饰静态方法
public synchronized static void helloStatic(){System.out.println("hello world static");
}// (2)修饰成员函数
public synchronized void hello(){System.out.println("hello world");
}// (3)直接定义代码块
public void test(){SynchronizedTest test = new SynchronizedTest(); synchronized (test){System.out.println("hello world");}
}
synchronized其底层说白了就是锁,所以呢,我们先从锁讲起
我们知道发生原子性的根源是CPU在执行完任意指令后都有可能发生线程切换。如果能够禁用线程切换的话那这个问题也就迎刃而解了。操作系统做线程切换是依赖 CPU 中断的,所以禁止 CPU 发生中断就能够禁止线程切换。
1、加锁和解锁操作在哪里体现的?
synchronized 的加锁和解锁是隐式实现的,可以查看字节码
2、synchronized 的锁对象是什么,也就是说锁定的是哪个对象?
- 如果修饰的是代码块,锁对象是我们自己指定的,指定哪个对象就锁定哪个对象。
- 如果修饰的是非静态方法,锁定的是当前实例对象
this。 - 如果修饰的是静态方法,锁定的是当前类的 Class 对象。
Linux内核提供的锁机制
1、Mutex(互斥量):pthread_mutex_t,通过对该结构的操作,来判断资源是否可以访问,Mutex属于sleep-waiting类型的锁,例如在多核机器上有两个线程A,B,如果此时锁被A持有,那么B就会被阻塞,在等待队列中等待。
2、Spin lock(自旋锁):pthread_spinlock_t,属于busy-waiting类型的锁,它不会引起调用者睡眠等待,如果获取不到锁则进入忙等待,它会不停的尝试去获取锁,俗称自旋,获取锁的性能相对较高,但是费CPU,所以自旋锁不应该被长时间的持有。
3、 Condition Variable(条件变量):pthread_cond_t,条件变量是利用线程间共享的全局变量,进行同步的一种机制
4、Read/Write Lock(读写锁):pthread_rwlock_t,读写锁是用来解决读多写少问题的,读操作可以共享,写操作是排他的。
5、semaphore:sem_t,信号量(semaphore)机制,也可用于互斥锁的实现
synchronized底层
public static void synClass() {Object obj = new Object();synchronized (obj) {}
}
我们看看这段代码的字节码文件
0 new #2 <java/lang/Object>3 dup4 invokespecial #1 <java/lang/Object.<init> : ()V>7 astore_18 aload_19 dup
10 astore_2
11 monitorenter
12 aload_2
13 monitorexit
14 goto 22 (+8)
17 astore_3
18 aload_2
19 monitorexit
20 aload_3
21 athrow
22 return
其中跟synchronized关键字相关的就是这样的字节码
monitorenter
........
monitorexit
monitorenter主要是获取监视器锁,monitorexit主要是释放监视器锁,所以我们的synchronized就是去获取这个监控锁对象,他会在我们的对象头中(markword)
markword图示如下:
加锁过程
前面我们看到了synchronized在字节码层面是对应monitorenter合monitorexit,而真正实现互斥的锁其实依赖操作系统底层的Mutex Lock来实现,首先要明确一点,这个锁是一个重量级的锁
整体锁升级的过程大致可以分为两条路径,如下:

1、偏向锁未启动,加锁默认加轻量级锁
轻量级锁:线程在自己的线程栈生成Lock Record,使用CAS的方式将markword设置为指向自己线程LOCK Record的指针,设置成功者得锁。竞争会让锁膨胀为重量级锁。
2、偏向锁启动
偏向锁,偏向的是第一个来获取锁的线程。所谓偏向锁,指的是获取锁的线程在markword中写自己的线程ID的过程,偏向锁升级为轻量级锁时首先要撤销偏向锁,如何设置轻量级锁。
偏向锁默认是打开的,但是启动有一个时延,默认4s,之所以要延迟,是因为JVM虚拟机自己有一些默认的启动线程,里面有好多sync代码,这些代码启动时就肯定会有竞争,如果直接使用偏向锁,就会造成偏向锁不断的进行锁撤销和锁升级的操作,效率较低。
我们平时使用synchronized注意点总结如下:
-
降低锁的等级
能用对象级别的,尽量别用类锁,能用实例变量的不要用静态变量
-
减少锁的时间 不需要同步执行的代码,能不放在同步块里面执行就不要放在同步快内,可以让锁尽快释放
-
减少锁的粒度 共享资源数决定锁的数量。有一组资源定义一把锁,而不是多组资源共用一把锁,增加并行度,从而降低锁竞争,典型如分段锁
-
减少加减锁的次数 假如有一个循环,循环内的操作需要加锁,我们应该把锁放到循环外面,否则每次进出循环,都要加锁
-
读写锁 业务细分,读操作加读锁,可以并发读,写操作使用写锁
-
善用volatile
volatile的控制比synchronized更轻量化,在某些变量上不涉及多步打包操作和原子性问题,可以加以运用。
如ConcurrentHashMap的get操作,使用的volatile而不是加锁
相关文章:
精心修炼Java并发编程(JUC)-volatile与synchronized关键字
volatile volatile 是 JVM 提供的 最轻量级的同步机制,中文意思是不稳定的,易变的,用 volatile 修饰变量是为了保证变量在多线程中的可见性,它表达的含义是:告诉编译器,对这个变量的读写,需要基…...
【ROS2】ROS2 与 ROS1 编码方式对比(Python实现)
目录 一、初始化和关闭节点二、发布者三、订阅者四、服务端五、客户端六、参数管理七、日志记录八、生命周期管理 ROS2 在 Python 编程中引入了一些新的概念和 API,这些变化使得代码更加模块化和易于维护。特别是 rclpy 库提供了更丰富的功能和更好的错误处理机制&a…...
ElasticSearch的下载和基本使用(通过apifox)
1.概述 一个开源的高扩展的分布式全文检索引擎,近乎实时的存储,检索数据 2.安装路径 Elasticsearch 7.8.0 | Elastic 安装后启动elasticsearch-7.8.0\bin里的elasticsearch.bat文件, 启动后就可以访问本地的es库http://localhost:9200/ …...
城市轨道交通运营控制指挥中心设计方案
为某城市轨道交通运营控制指挥中心(OCC)的设计提供方案时,我们需要考虑到多个方面的需求,包括系统架构、设备选择、功能实现、数据流与监控、通信管理等。以下是一个综合性的设计方案,涉及系统硬件和软件的选择、布局规划、安全性等方面,以确保指挥中心的高效运作、实时监…...
多目标优化算法:多目标河马优化算法(MOHOA)求解ZDT1、ZDT2、ZDT3、ZDT4、ZDT6,提供完整MATLAB代码
一、河马优化算法 河马优化算法(Hippopotamus optimization algorithm,HO)由Amiri等人于2024年提出的一种模拟自然界中河马觅食行为的新型群体智能优化算法。该算法由Mohammad Hussein Amiri等人于2024年2月发表在Nature旗下子刊《Scientifi…...
线程与进程的个人理解
进程(Process): 一个程序在执行时,操作系统为其分配的资源(如内存、CPU 时间等)构成了一个进程。每个进程都有自己的独立的地址空间、堆栈和局部变量,它们之间不共享内存(除非通过特…...
vscode的项目给gitlab上传
目录 一.创建gitlab帐号 二.在gitlab创建项目仓库 三.Windows电脑安装Git 四.vscode项目git上传 一.创建gitlab帐号 二.在gitlab创建项目仓库 图来自:Git-Gitlab中如何创建项目、创建Repository、以及如何删除项目_gitlab新建项目-CSDN博客) 三.Windows电脑安…...
企业微信定位打卡
废话少说:定位修改软件链接奉上 一、定位打卡原理 GPS定位:企业微信可以利用手机的GPS功能进行定位,这是一种基于卫星的定位技术,能够提供相对精确的位置信息,通常精确度在20米以内。这种方式耗电较大,且在…...
libaom 源码分析:码率控制介绍
码率控制 命令行码率控制选项:可以看到码率控制包括丢帧、resize、超分、码控模式、目标码率、目标上限下限(类似 x264、x265 中的 VBV)、码控偏置、GOP 码率等。Rate Control Options:--drop-frame=<arg> Temporal resampling threshold (buf %)--resize-mo…...
RK3568平台开发系列讲解(DMA篇)DMA engine使用
🚀返回专栏总目录 文章目录 一、申请DMA channel二、配置DMA channel的参数三、获取传输描述(tx descriptor)四、启动传输沉淀、分享、成长,让自己和他人都能有所收获!😄 📢DMA子系统下有一个帮助测试的测试驱动(drivers/dma/dmatest.c), 从这个测试驱动入手我们了解…...
C++中的函数对象
C 中函数对象的定义和特点 定义:函数对象(Function Object)也叫仿函数(Functor),是一个类,这个类重载了函数调用运算符()。当创建这个类的对象后,可以像使用函数一样使用这个对象&am…...
Linux指标之平均负载(The Average load of Linux Metrics)
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:Linux运维老纪的首页…...
盛最多水的容器
本节将数组与坐标轴共同组成一个容器,通过改变容器的两个端点使容器装的水最多,容器两个端点不断移动可以通过左右指针算法解决. 问题描述: 给定两个非负整数k1,k2...km每个数代表坐标中的一个点(i,ki).在坐标内绘制m条垂线,垂直线i的两个端点分别为(i,k1)和(i,0)找出其中的两…...
光伏功率预测!Transformer-LSTM、Transformer、CNN-LSTM、LSTM、CNN五模型时序预测
目录 预测效果基本介绍程序设计参考资料 预测效果 基本介绍 Transformer-LSTM、Transformer、CNN-LSTM、LSTM、CNN五模型多变量时序光伏功率预测 (Matlab2023b 多输入单输出) 1.程序已经调试好,替换数据集后,仅运行一个main即可运行,数据格式…...
java全栈day10--后端Web基础(基础知识)
引言:只要能通过浏览器访问的网站全是B/S架构,其中最常用的服务器就是Tomcat 在浏览器与服务器交互的时候采用的协议是HTTP协议 一、Tomcat服务器 1.1介绍 官网地址:Apache Tomcat - Welcome! 1.2基本使用(网上有安装教程,建议…...
使用爬虫时,如何确保数据的准确性?
在数字化时代,数据的准确性对于决策和分析至关重要。本文将探讨如何在使用Python爬虫时确保数据的准确性,并提供代码示例。 1. 数据清洗 数据清洗是确保数据准确性的首要步骤。在爬取数据后,需要对数据进行清洗,去除重复、无效和…...
Burp入门(4)-扫描功能介绍
声明:学习视频来自b站up主 泷羽sec,如涉及侵权马上删除文章 感谢泷羽sec 团队的教学 视频地址:burp功能介绍(1)_哔哩哔哩_bilibili 本文介绍burp的主动扫描和被动扫描功能。 一、主动扫描 工作原理: 主动…...
Tourtally:颠覆传统的AI智能旅行规划革命
# Tourtally:颠覆传统的AI智能旅行规划革命 在快速变化的旅行科技世界里,一个划时代的平台正在重新定义我们探索世界的方式。让我们一起认识 Tourtally,这个由人工智能驱动的旅行规划助手,正在彻底改变旅行体验。 ## 旅行规划的…...
chrome允许http网站打开摄像头和麦克风
第一步 chrome://flags/#unsafely-treat-insecure-origin-as-secure 第二步 填入网址,点击启用 第三步 重启 Chrome:设置完成后,点击页面底部的 “Relaunch” 按钮,重新启动 Chrome 浏览器,使更改生效。...
视觉经典神经网络与复现:深入解析与实践指南
目录 引言 经典视觉神经网络模型详解 1. LeNet-5:卷积神经网络的先驱 LeNet-5的关键特点: 2. AlexNet:深度学习的突破 AlexNet的关键特点: 3. VGGNet:深度与简洁的平衡 VGGNet的关键特点: 4. ResNe…...
MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...
(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...
第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...
微服务商城-商品微服务
数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...
工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配
AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...
微信小程序云开发平台MySQL的连接方式
注:微信小程序云开发平台指的是腾讯云开发 先给结论:微信小程序云开发平台的MySQL,无法通过获取数据库连接信息的方式进行连接,连接只能通过云开发的SDK连接,具体要参考官方文档: 为什么? 因为…...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...
今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存
文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...
