Synchronized和volatile以及final语义

Java 内存模型(JMM)——深入happens-before、可见性、volatile、synchronized 与 final 语义! ㊗️本期内容已收录至专栏《Java核心实操(进阶版)》,持续完善知识体系与项目实战,建议先订阅收藏,后续查阅更方便~ 阅读详情

synchronized

synchronized 是早期的线程同步的实现,通过给方法或者 代码块加上synchronized修饰 可以保证在多线程环境下只有一个线程进入到语句中执行
synchronized 是通过加入monitor(监视器) 也就说是锁,来保证线程安全的,并且获取监视器的所有权是具有互斥性,就是说只有一个线程能获取锁,另外锁也具有重入性,如果是不同的方法使用的是同一个锁对象,当前线程在进入另一个synchronized同步语句中是不需要再次获取锁
对象锁:
锁住的是该类的一个对象, 任意一个对象都可以当作锁
有且只有一个获取该对象锁的线程进入synchronized同步语句
类锁:
锁住的是该类,好比是个全局锁,该类所有实例对象的锁且只有一个线程能获取

对象锁类锁
1.修饰普通方法public synchronized void method1()1. 修饰静态方法 public static synchronized void method2()
2.修饰同步代码块 synchronized (this)

其他
JVM规范中对于monitorenter和monitorexit的描述:

  • monitorenter
    每个对象有一个监视器锁(monitor)。当monitor被占用时就处于锁定状态,线程执行monitorcenter指令时尝试获取monitor的所有权,过程如下: • 如果monitor的进入数为0,则该线程进入monitor,然后将进入数设置为1,该线程即为monitor的所有者。•如果线程已经占有该monitor,只是重新进入,则进入monitor的进入数加1。•如果其他线程已经占用monitor,则该线程进入阻塞状态,直到monitor的进入数为0,再重新尝试获取monitor的所有权
  • monitorexit
    执行monitorexit的线程必须是object所对应的monitor的所有者。指令执行时,monitor的进入数减1,如果减1后进入数为0,则线程退出monitor,不再是这个monitor的所有者。其他被这个monitor阻塞的线程可以尝试去获取这个monitor的所有权

volatile

volatile是一个修饰变量的修饰符,volatile修饰的变量能保证多线程之间的可见性 即一个线程修改了变量 其他线程能立即感知到,但是保证不了 原子性,是一种比锁更轻量级同步实现方法,同时能够禁止指令重排序带来的线程安全问题;

指令重排:
1. 编译器优化的重排序。编译器在不改变单线程程序语义的前提下,可以重新安排语句的执行顺序。
2. 指令级并行的重排序。现代处理器采用了指令级并行技术(Instruction-LevelParallelism,ILP)来将多条指令重叠执行。如果不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序。
3. 内存系统的重排序。由于处理器使用缓存和读/写缓冲区,这使得加载和存储操作看上去可能是在乱序执行。
如果两个数据存在依赖性,则不会发生指令重排

volatile 是通过内存屏障来禁止指令重排序
内存屏障: 又称为内存栅栏,是一个cpu指令
内存屏障分为两种:Load Barrier 和 Store Barrier即读屏障和写屏障。
内存屏障有两个作用:

1.阻止屏障两侧的指令重排序;
2.强制把写缓冲区/高速缓存中的脏数据等写回主内存,让缓存中相应的数据失效。

对于Load Barrier来说,在指令前插入Load Barrier,可以让高速缓存中的数据失效,强制从新从主内存加载数据;
对于Store Barrier来说,在指令后插入Store Barrier,能让写入缓存中的最新数据更新写入主内存,让其他线程可见。

java的内存屏障通常所谓的四种即LoadLoad,StoreStore,LoadStore,StoreLoad实际上也是上述两种的组合,完成一系列的屏障和数据同步功能。

LoadLoad屏障对于这样的语句Load1; LoadLoad; Load2,在Load2及后续读取操作要读取的数据被访问前,保证Load1要读取的数据被读取完毕
StoreStore屏障对于这样的语句Store1; StoreStore; Store2,在Store2及后续写入操作执行前,保证Store1的写入操作对其它处理器可见
LoadStore屏障对于这样的语句Load1; LoadStore; Store2,在Store2及后续写入操作被刷出前,保证Load1要读取的数据被读取完毕
StoreLoad屏障对于这样的语句Store1; StoreLoad; Load2,在Load2及后续所有读取操作执行前,保证Store1的写入对所有处理器可见。它的开销是四种屏障中最大的。在大多数处理器的实现中,这个屏障是个万能屏障,兼具其它三种内存屏障的功能

在每个volatile写操作前插入StoreStore屏障,在写操作后插入StoreLoad屏障;
在每个volatile读操作前插入LoadLoad屏障,在读操作后插入LoadStore屏障;

由于内存屏障的作用,避免了volatile变量和其它指令重排序、线程之间实现了通信,使得volatile表现出了锁的特性。
volatile 性能:

volatile 的读性能消耗与普通变量几乎相同,但是写操作稍慢,因为它需要在本地代码中插入许多内存屏障指令来保证处理器不发生乱序执行。

final 在并发中的作用

写 final 域的重排序规则

写 final 域的重排序规则禁止把 final 域的写重排序到构造函数之外。这个规则的实现包含下面 2 个方面:

  1. JMM 禁止编译器把 final 域的写重排序到构造函数之外。
  2. 编译器会在 final 域的写之后,构造函数 return 之前,插入一个 StoreStore 屏障。这个屏障禁止处理器把 final 域的写重排序到构造函数之外。

(对象逸出,或者说是 构造函数析解逸出)

写内存语义:在构造函数内对一个 final 域的写入,与随后将对象引用赋值给引用变量,这两个操作不能重排序。
读内存语义:初次读一个包含 final 域的对象的引用,与随后初次读这个 final 域,这两个操作不能重排序。
【内存语义的实现原理】

在 final 域的写之后,构造函数 return 之前,插入一个 StoreStore 屏障。
在读 final 域之前插入一个 LoadLoad 屏障。
软件测试工程师最常用的Linux系统命令大全(汇总) cd命令这是一个非常基本,也是大家经常需要使用的命令,它用于切换当前目录,它的参数是要切换到的目录的路径,可以是绝对路径,也可以是相对路径。 阅读详情

相关推荐

300个fpga练手项目推荐

• 按键设置BPM,LED和蜂鸣器同步打拍(支持4/4、3/4拍)• 例:先实现DDR3控制器(基础),再构建视频处理流水线(集成)◦ 驱动小型e-Paper显示日期/时间(SPI接口,静态刷新)◦ 音频输入经FFT后,用LED柱状显示频率能量(8频段简化)◦ 通过HC-05模块接收手机指令,控制电机方向(前进/后退)• 随机点亮LED,用按钮响应,数码管显示反应时间(毫秒级)• 8个LED旋转闪烁,按钮停止后显示中奖编号(带减速动画)• 用4方向按键输入手势(如→→←↑),正确后点亮绿色LED。

qq_62784677的博客 7637

JAVA的关键字:final && synchronized

根据程序上下文环境,Java关键字final有“这是无法改变的”或者“终态的”含义,它可以修饰非抽象类、非抽象类成员方法和变量。 (1)final类不能被继承,没有子类,final类中的方法默认是final的。 (2)final方法不能被子类的方法覆盖,但可以被继承。 (3)final成员变量表示常量,只能被赋值一次,赋值后值不再改变。 (4)final不能用于修饰构造方法。 注

zhandoushi的专栏 4570

C语言头文件完全解析(连“#”我都给你讲明白)

C语言头文件完全解析 引言 本文将尽量详细的介绍c语言的头文件所包含的知识,如有错误,还望指正。 萌新们肯定疑惑为什么每次打代码都要写一个所谓的头文件(如:#include<stdio.h>),这里先简单让大家有个了解,你所用的 printf("%d",a)就是这个 stdio里的东西,如果没有这个头文件,编译器都不知道 printf是个什么东东。所以头文件就是一个准备好的大仓库,你可...

CRAZY_eyes的博客 7万+

关键字回顾(final/finally/finalize()、Synchronized、volatile、static)

1. final, finally, finalize的区别 final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。 finally是异常处理语句结构的一部分,表示总是执行。 finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源 回收,例如关闭文件等。 1.1 final 当用fin...

Zhxin606a的博客 433

Jetpack Compose Navigation实战:从基础到高级导航模式

本文全面解析Jetpack Compose Navigation在Android开发中的应用,从基础导航实现到高级模式(如单任务/单顶模式),涵盖参数传递、嵌套导航、深层链接等核心功能。通过实战代码示例展示如何优化导航性能,并与ViewModel、Hilt等架构组件整合,为开发者提供高效的Compose导航解决方案。

pz890123456的博客 372

量化交易如何利用涨停板策略收割散户

量化交易通过算法筛选特定特征的股票,在早盘建立底仓后,利用大单拉升制造抢筹假象,吸引散户跟风买入。这种策略利用了散户的认知偏差,如锚定效应和从众心理,导致次日低开闷杀。从技术实现来看,量化策略通过控制买入量、隐藏真实意图等手段,精准执行隔日砸策略。对于短线交易者而言,理解量化资金的运作逻辑和识别危险涨停板的特征至关重要,这包括观察封板时间、盘口挂单、量价关系等多维度数据。在算法主导的市场中,散户需要升级交易工具和策略,从预测走势转向应对走势,才能避免成为量化策略的牺牲品。

weixin_33046983的博客 285

Java并发编程:如何正确使用 volatile、synchronized 和 final 关键字

本文介绍了 Java 中的 volatile、synchronized 和 final 三个关键字的作用、原理以及使用场景。volatile 关键字可以保证可见性和有序性,synchronized 关键字可以保证可见性和有序性,同时还可以保证原子性,final 关键字可以保证变量的不可变。在实际开发中,需要根据具体的需求选择合适的关键字来保证程序的正确性和性能。

乐只悠悠 1254

从零配置ORB-SLAM3:TUM-VI数据集yaml文件参数调优指南

本文深入解析了ORB-SLAM3在TUM-VI数据集上的yaml配置文件参数调优方法。针对双目惯性模式,详细拆解了相机标定、IMU噪声模型和ORB特征提取三大模块的关键参数,解释了其原理与影响,并通过实战案例展示了如何通过调整特征点数量、FAST阈值及IMU噪声参数,有效提升系统在低纹理环境下的鲁棒性和轨迹精度。

weixin_29071809的博客 151

Java中Synchronized、final的作用

Synchronized的用法 synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种:   1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;   2. 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;   3. 修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;   4. 修改一个类,其作用的范围是synchronized后面括

weixin_43757333的博客 1539

陀螺仪选型避坑指南:为什么IMU660RA是智能车竞赛的性价比之选?

本文针对智能车竞赛场景,提供陀螺仪选型避坑指南,并深度解析为何IMU660RA成为性价比之选。文章指出,竞赛选型应避免盲目追求高性能“黑盒”模块,而应注重原始数据获取与算法开发。IMU660RA以其良好的常温稳定性、适中的噪声水平、极致的性价比和丰富的生态支持,成为帮助参赛者深入理解姿态解算原理、进行“白盒开发”的理想教学与实践平台。

tech5的博客 879

QGIS004:【05矢量属性表】-保留字段、删除字段、添加唯一值索引字段、添加字段到属性表、添加自增量字段、添加XY字段到图层、文本型转浮点型、重构字段、重命名字段

摘要:QGIS矢量属性表工具箱包括保留字段、删除字段、添加唯一值索引字段、添加字段到属性表、添加自增量字段、添加XY字段到图层、文本型转浮点型、重构字段、重命名字段等选项,本文介绍各选项的基本操作。

qq_31762031的博客 2311

Java中的`volatile`、`synchronized` 和 `final` 关键字详解

定义与作用: 关键字用于修饰变量,确保变量对所有线程的可见性。当一个变量被声明为 后,它会告诉JVM这个变量是不稳定的,每次使用它都需要从主存中重新读取,而不是使用已经缓存在各个线程工作内存中的副本。这样就避免了线程间因缓存不一致而导致的数据问题。使用场景:注意事项:定义与作用: 关键字可以用于方法或代码块上,以确保在同一时刻只有一个线程可以执行该段代码。它有两种用法:修饰方法和修饰代码块。使用场景:注意事项:定义与作用: 关键字用于修饰类、方法和变量。对于变量而言, 意味着一旦变量被初始化后,其值就不能

m0_61431263的博客 636

ESP32 WIFI 智能巡线小车设计与实现(四足 / 四轮通用)

本文设计的 ESP32 WIFI 智能巡线小车,硬件模块化、软件轻量化,兼容四足与四轮两种结构,实现了自动巡线与 WIFI 远程控制双功能。系统成本低、易上手,适合嵌入式初学者学习 WIFI 通信、传感器应用、运动控制等核心知识点,也可在此基础上扩展蓝牙控制、避障、视觉识别等功能。

weixin_42300449的博客 151

volatile、synchronized、final内存语义

volatile内存语义 当写volatile变量时,JMM会把该线程对应的本地内存中的共享变量刷新到主内存。 当读volatile变量时,volatile变量的每次使用都必须从主内存刷新最新的值。 JMM针对编译器对编译器指定的volatile重排序规则表 是否能重排序 第二个操作 第一个操作 普通读/写 volatile读 volat...

lizc_lizc的博客 403

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Java内存模型<二> _ volatile/synchronized/final内存语义

一、volatile的内存语义

爱我所爱0505 685

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

volatile、synchronized、final

目录 一、volatile (一)什么是volatile (二)volatile的实现 (三)volatile内存语义 二、synchronized (一)什么是synchronized (二)锁优化 1.偏向锁 2.轻量级锁 (三)synchronized的实现 (四)synchronized的使用 三、final (一)什么是final 1.final类 2.fi...

鹿与森的博客 847

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

深入JMM内存模型解析volatile、synchronized的内存语义

管道的实质是一个内核缓冲区,需要通信的两个进程各在管道的两端,进程利用管道传递信息。

m0_69632475的博客 448

Java多线程与高并发专题——保障可见性和有序性

Java多线程与高并发专题——保障可见性

从知识输入到知识输出 1171

java并发之Volatile和Final

部分内容来自网络,如有版权问题请联系 文章目录Volatile(易变)内存语义保证可见性与有序性synchronized和 volatileHappens-beforefinal内存语义 Volatile(易变) 首先介绍一下指令重排序:java内存模型允许编译器和处理器对指令重排序以提高运行性能,并且只会对不存在数据依赖性的指令重排序。 内存语义 当写一个 volatile 变量时,JMM 会把该线程对应的本地内存中的共享变量值刷新到主内存。 当读一个 volatile 变量时,JMM 会把该线程对应的

weixin_54558363的博客 497

Java内存模型系列(三)jvm如何实现内存模型

0x01 volatile关键字 作用一:保证变量可见性 volatile关键字修饰变量,保证此变量的写操作对所有线程的都是立即可见的。但是基于volatile的运算操作不是立即可见的(非线程安全) 特殊:以下两种场景需要要保证其操作的原子性 一:运算结果并不依赖变量的当前值,或者能够确保只有单一的线程修改变量的值 二:变量不需要与其他的状态变量共同参与不变约束 作用二:禁止指令重排序 在单线程...

fangmenghao的专栏 233

Volatile、锁、final内存语义

前言 本文主内容 主要介绍关键字的 内存语义 volatile的内存语义 锁的内存语义 finnal的内存语义 一、Volatile 1.1 Volatile的特性 可见性: 对一个volatile变量的读,总是能看到任意线程对这个变量最后的写入 原子性: 对任务单个volatile变量的读/写具有原子性(包括64位的long和double),但是volatile++ 这种操作不具备原子性;(仅仅是读写具备原子性) volatile读写内存语义: volatile读: 当读一个volatile变量时,

莫失莫忘的博客 328

基础篇:深入JMM内存模型解析volatile、synchronized的内存语义

深入JMM解析volatile、synchorized的内存语义 1 CPU高速缓存、MESI协议 2 指令重排序和内存屏障指令

潜行前行的专栏 1846

Java核心关键字深度拆解:static、volatile、synchronized底层原理与面试实战

在Java技术体系中,关键字不仅是语法符号,更是连接开发者与JVM运行时行为的桥梁。理解static、final、volatile、synchronized等核心关键字的底层机制,是迈向高级工程师的关键一步。本文从JVM类加载、内存模型、对象头锁状态等基础原理出发,剖析这些关键字在并发编程、不可变设计、序列化控制中的技术价值,并结合实际工程中的典型踩坑案例,梳理出从状态标志到锁升级的完整知识链条。无论是准备技术面试、巩固Java基础,还是提升实战编码能力,都能从中获得系统化的认知框架,实现对关键字从“背八股

weixin_33428613的博客 316

volatile 修饰数组_基础篇:深入JMM内存模型解析volatile、synchronized的内存语义

先介绍下多进程多线程在linux几种通信方式管道:管道的实质是一个内核缓冲区,需要通信的两个进程各在管道的两端,进程利用管道传递信息信号:信号是软件层次上对中断机制的一种模拟,进程不必阻塞等待信号的到达,信号可以在用户空间进程和内核之间直接交互消息队列:消息队列是消息的链表,存放在内存中并由消息队列标识符标识,允许多个进程向它写入与读取消息共享内存:多个进程可以可以直接读写同一块内存空间...

weixin_39884877的博客 184

Java的同步原语——volatile,synchronized和final

前言 上一篇博客写了java内存模型的基础,也就是未同步的情况,未同步的线程运行顺序不得而知,运行效果也不一定,安全性是比较低的。本篇博客将谈谈java的三个同步原语。 volatile volatile变量自身具有下列特性 可见性:对一个volatile变量的读,总是能看到任意线程对这个变量最后的写入。 原子性:对任意单个volatile变量的读、写具有原子性,但是对于volatile++这种复...

ali_lili的博客 797

【JVM原理详解】45-final域的内存语义

this逃逸指在构造函数执行期间,this在构造函数中启动线程,并把this传进去在构造函数中注册回调/监听器,回调中引用this在构造函数中把this赋给静态变量或共享集合。

gaochufukanyongren的博客 12
上一篇: java线程基础
下一篇: JAVA线程池
xiaoduup
博客等级 码龄9年 23粉丝 83原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值