java中共享变量的可见性:volatile与synchronized 

线程共享和协作(二):Synchronized、ThreadLocal、Volatile如何实现线程共享 共享对象 使用Java编写线程安全的程序关键在于正确的使用共享对象,以及安全的对其进行访问管理。Java的内置锁可以保障线程安全,对于其他的应用来说并发的安全性是使用内置锁保障了线程变量使用的边界。谈到线程的边界问题,随之而来的是Java内存模型另外的一个重要的含义,可见性。Java对可见性提供的原生支持是volatile关键字。 Atomic 作用 对于原子操作类,Java的concurrent并发包中主要为我们提供了这么几个常用的:AtomicInteger、AtomicLong、AtomicBoole 阅读详情

1. volatile 由关键字volatile修改的线程共享变量具有内存可见性,每次读取此变量时都会从主内存中读取,每次修改此变量时都会写到主内内存中,是真正的在任何时候都具有可见性。原理:在执行cpu命令层面应用CAS算法,实现原子性。

2. final final 修饰变量时,初衷是告诉编译器:这个变量生而不变,可以可劲儿优化,对于boolean,int等类型变量没有问题,但对于List等对象就不会保证可见性当我们修改List中元素时;而volatile是对于包括List的所有类型都具有可见性;

3. synchronized 

以下内容引用于https://www.cnblogs.com/hupu-jr/p/8397911.html,有少许修改。

最近在看<Java并发编程实战>这本书,看到共享变量的可见性,其中说到“加锁的含义不仅仅局限于互斥行为,还包括内存可见性”。

我对于内存可见性第一反应是volatile:被volatile修饰的变量能够保证每个线程能够获取该变量的最新值,从而避免出现数据脏读的现象。

原因是volatile修饰的共享变量进行写操作的时候会多出Lock前缀的指令,通过多处理器的缓存一致性协议,来保持变量的同步更新。

但是我却没明白“加锁”与“可见性”这句话表达的意思,仔细思考下确实是这样子的:

2个线程中在对共享变量的读取或者写入都进行加锁处理,因为线程对应的都是同一把锁对象,所以相互会排斥。但是就算这样子也不能说明内存可见性的。其实真正解决这个问题的是JMM关于Synchronized的两条规定: 

1、线程解锁前,必须把共享变量的最新值刷新到主内存中; 
2、线程加锁时,将清空工作内存中共享变量的值,从而使用共享变量需要从主内存中重新读取最新的值(加锁与解锁需要统一把锁) 

线程执行互斥锁代码的过程: 
1.获得互斥锁 
2.清空工作内存 
3.从主内存拷贝最新变量副本到工作内存 
4.执行代码块 
5.将更改后的共享变量的值刷新到主内存中 
6.释放互斥锁 

http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#incorrectlySync

这里提到synchronized会保证对进入同一个监视器的线程保证可见性。比如线程 t1修改了变量,退出监视器之前,会把修改变量值v1刷新的主内存当中;当线程t2进入这个监视器时,如果有某个处理器缓存了变量v1,首先缓存失效,然后必须重主内存重新加载变量值v1(这点和volatile很像)。这里语义的解读只是说了对于同一个监视器,变量的可见性有一定的方式可寻,非同一个监视器就不保证了。

三、总结

synchronized具有内存可见性,为了确保所有线程能够看到共享变量的值是最新的,所有执行读操作或写操作的线程都必须在同一个锁上同步。

基于STM32L4XX、HAL库的 ATGM336H GPS定位模块驱动程序设计 / 转换为km/h。// 定位状态: 0=无效, 1=GPS定位, 2=差分定位。// GPS解析数据。支持GPS/BeiDou/GLONASS/Galileo/QZSS多系统联合定位。// 回调函数(需要在HAL_UART_RxCpltCallback中调用)// 地面速度(km/h)// 海拔高度(m) 阅读详情

相关推荐

IMA知识库:从0到1的架构设计与实践

本文探讨了AI时代知识库系统的架构设计与演进路径。通过分析知识入库、知识管理和知识应用三大核心业务流程,提出了应对数据多样性、处理标准化、流量洪峰等挑战的解决方案。重点介绍了基于统一数据格式的解耦设计、异步处理架构、服务拆分策略以及权限安全体系,构建了一个稳定、高效且可扩展的知识库系统。文章强调优秀架构需要持续演进,通过识别薄弱点不断优化,最终实现技术方案与业务需求的平衡。

lovehu6686的博客 1737

锁(三)锁的种类验证

一、预备知识: 二、使用案例:

w_t_y_y的博客 310

在 Zemax 非序列模式下建立干涉仪模型

Zemax 利用其相干检测功能,将到达探测器的射线的能量相干地组合起来,同时考虑每条检测到的射线的幅度和相位。从对这些干涉条纹的定量评估来看,光学干涉仪具有广泛的应用,包括在天文学中用于测量天体的大小,在计量学中用于精确测量距离,在显微镜中用于提高分辨率,以及在物理和工程的各个领域中用于检测条件的微小变化。在光学干涉仪中,使用的是光波。非相干和相干相加的总功率是守恒的,但相干光束的峰值辐照度应该是非相干光束总和的 2 倍,这是理所当然的。请注意,条纹的缺失是显而易见的,因为不再从相干的角度观察探测器。

jkh920184196的博客 2381

java之用volatile和不用volatile的区别

在当前的Java内存模型下,线程可以把变量保存在本地内存(比如机器的寄存器)中,而不是直接在主存中进行读写。这就可能造成一个线程在主存中修改了一个变量的值,而另外一个线程还继续使用它在寄存器中的变量值的拷贝,造成数据的不一致。  要解决这个问题,只需要像在本程序中的这样,把该变量声明为volatile(不稳定的)即可,这就指示JVM,这个变量是不稳定的,每次使用它都到主存中进行读取。一般

天元喜羊羊的博客 6万+

STRING数据库的蛋白质相互作用(PPI)网络分析

在转录调控相关的文献中,我们经常能够看到这样的蛋白质相互作用网络(protein protein interaction network,PPI network)。具体而言,这些相关的文献中首先通过RNA-seq、表达谱芯片或者蛋白质组分析等,找到了在不同分组样本间一系列的差异表达基因或蛋白。

weixin_43029125的博客 9454

KUKA机器人编程实战:5分钟搞定组输入与组输出的信号配置(附代码示例)

本文详细介绍了KUKA机器人编程中组输入与组输出的信号配置方法,通过5分钟快速掌握核心技巧。文章包含信号声明语法、典型配置流程及高级应用技巧,并附有代码示例,帮助工程师高效实现机器人与外部设备的通信。

efc123456的博客 851

浅谈Java中的volatile关键字

(1)内存可见性:         volatile是Java提供的一种轻量级的同步机制,在并发编程中,它也扮演者重要角色。同Synchronized相比(Synchronized称为重量级锁),volatile更轻量级,能保证多个线程共享资源的可见性。 public class TestVolatile { boolean status = false; /** ...

蜜蜂采蜜 468

【WRF数据准备】气象驱动数据-ERA5再分析数据(Copernicus)

【WRF数据准备】气象驱动数据-ERA5再分析数据

WW、forever的博客 5529

JMM内存模型

一、cpu的缓存模型 简化版 二、JMM内存模型 Java多线程内存模型跟cpu缓存模型类似,基于cpu缓存模型来建立的 1、数据原子操作 (1)read(读取) 从主内存读取数据 (2)load(载入) 将主内存读取到的数据写入工作内存 (3)use(使用) 从工作内存读取数据计算 (4)assign(赋值) 将计算好的值重新赋值到工作内存中 (5)store(存储) 将工作内存数据写入主内存 (6)write(写入) 将store过去的变量值赋值给主内存中的变

勇心在馨 345

AI测试入门:基于 RAG 的 LLM 应用程序的测试方法「详细介绍」

一个典型的 RAG 架构包括一个检索器(对知识库进行矢量搜索检索上下文的组件)和一个生成器(从检索器中获取检索上下文以构建提示并生成自定义 LLM 响应作为最终输出的组件)。在大多数情况下, 知识库”由存储在向量数据库(如 ChromaDB)中的向量嵌入组成。

blues_C的博客 1869

2021-10-29【微生物】丨基于qiime2工具16S/ITS分析全套流程(上)

目录摘要工具与方法使用命令结果展示总结二级目录三级目录 摘要 前两个月项目特别多,最近终于有机会闲下来写点文章,把之前搭建的流程梳理一遍。前同事分析16S/ITS使用的qiime1,我接手后感觉不太适应,希望能够使用新版本来搭建,于是花了几天时间重新搭了这个流程, 工具与方法 使用工具:qiime2 使用版本:qiime2-2021.4 参考文档:https://docs.qiime2.org/2021.4/(最新版本2021.8) 使用命令 在这里插入代码片 结果展示 总结 二级目录 三级目录 ...

1万+

多线程——volatile关键字与内存可见性

如果一个变量在多个线程的工作内存中都存在副本,那么这个变量就是这几个线程的共享变量。

xeswzb的博客 526

利用Python实现Springer文献关键词爬虫

🔧 如何分析Springer的搜索结果HTML结构🕷️ 编写高性能异步爬虫抓取论文元数据📊 使用Pandas导出Excel🧠 如何处理作者、摘要、DOI等字段🔄 如何优化爬虫稳定性与可扩展性。

2201_76125261的博客 415

java学习12--线程的可见性,synchronized,volatile使用

1.可见性 一个线程对共享变量的修改能够及时被其他线程访问到。 JMM模型中所有变量存储在主内存,每个线程中有独立工作内存,工作内存保留的是变量在主内存中的副本 策略机制:不同线程无法直接访问其他线程工作内存中的变量,线程中变量的传递需要通过主存,因此要保证线程写操作后将共享变量值从工作内存刷新到主内存   1.final 2.synochronized 3.volatile 2.s

zylzl123的专栏 356

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Java多线程之内存可见性

什么叫“可见性”? 一个线程对共享变量值的修改,能够被其他线程及时看到。 共享变量:如果一个变量在多个线程的工作内存中存在副本,那么这个变量就是这几个线程的共享变量。 所有变脸都存在主内存中,每个线程都有自己独立的工作内存,里面保存该线程使用大的变量副本,关系如下图所示: 多线程遵守的两条规定 1.线程对共享变量所有的操作都只能在自己的工作内存中完成,无法直接从主内存...

weixin_30322405的博客 203

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Java并发编程之synchronized 与 volatile

本文简单的介绍下synchronized和volatile两大关键字的区别

潇歌的博客 430

getmenuiteminfo无法读取内存_Java内存可见性

如果一个线程对共享变量的修改,能够被其它线程看到,那么就能说明共享变量在线程之间是可见的。如果一个变量在多个线程的工作内存中都存在副本,那么这个变量就是这几个线程的共享变量。Java内存模型(Java Memory Model,JMM)描述了Java程序中各种变量(线程共享变量)的访问规则,以及在JVM中将变量存储到内存和从内存中读取出变量这样的底层细节。所有的变量都储存在主内存中。每个线程都有自...

weixin_39743064的博客 98

Java volatile与synchronized终极对决:从轻量级标记到重量级同步的全面剖析

volatile是Java中最轻量级的同步机制,它确保共享变量的可见性和有序性,但不保证原子性。是Java的重量级同步机制,它同时保证原子性可见性和有序性,以互斥排他的方式控制并发访问。📌一句话理解:volatile是"通知大家我改了"(轻量级标记);synchronized是"关门独享,谁都别打扰"(重量级锁)。volatile是轻量级的可见性/有序性保障工具,不涉及锁操作;synchronized是全能的互斥同步机制,同时保证原子性、可见性和有序性。

✨ 欢迎来到【Seal ^_^ 的优快云博客】!✨ 226

【JAVA基础面经】进程安全问题(synchronized and volatile)

线程的安全主要指的是由于操作系统进行线程调度的时候是否会带来问题一个经典的线程不安全的例子是两个线程分别自增对应的数字,如下所示,两个线程总共相加应该为100000的情况,但最终得到的结果总在50000和100000之间count++;i<50000;});i<50000;});t1.start();t2.start();//在t1、t2执行完之后再打印count的结果//在main中打印两个线程执行的结果。

2301_81831660的博客 727

volatile vs synchronized

今天来聊一聊Java并发编程中两个常用的关键字:volatile和synchronized。 在介绍这两个关键字之前,首先要搞明白并发编程中的两个问题: 线程之间是如何通信的 线程之间如何同步 Java内存模型 Java线程的通信由Java内存模型(JMM)控制,Java内存模型的抽象如图: https://www.jianshu.com/p/8c574a6db31b” title=...

K_Ohaha的博客 279

Java # volatile关键字

在JDK1.2之前,Java的内存模型实现总是从主存中读取变量。

xyz_xiaoyuzhou的博客 123

【Java学习记录】volatile与synchronized

【Java学习】volatile与synchronized 一、首先谈谈JMM内存模型 JMM内存模型规定了线程的工作机理:即所有的共享变量都存储在主内存,如果线程需要使用,则拿到主内存的副本,然后操作一番,再放到主内存里面 提取关键字:JMM内存模型、共享变量、主内存,主内存副本 JMM内存模型:JMM决决定一个线程对共享变量的写入何时对对另一个线程可见。从抽象的角度来看,JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存中,每个线程都有一个***私有的本地内存***,本

Bob7856的博客 366

深入理解volatile与synchronized

1.volatile 1.1.为什么要使用volatile volatile是轻量级的synchronized,它在多处理器开发中保证了共享变量的“可见性”。可见性的意思是当一个线程修改一个共享变量时,另外一个线程能读到这个修改的值。它比synchronized的使用和执行成本更低,因为它不会引起线程上下文的切换。 1.2.volatile的定义 Java编程语言允许线程访问共享变量,为了

ringwan的博客 498

JMM volatile

2.2. 讲一下 JMM(Java 内存模型) 在 JDK1.2 之前,Java 的内存模型实现总是从主存(即共享内存)读取变量,是不需要进行特别的注意的。而在当前的 Java 内存模型下,线程可以把变量保存本地内存(比如机器的寄存器)中,而不是直接在主存中进行读写。这就可能造成一个线程在主存中修改了一个变量的值,而另外一个线程还继续使用它在寄存器中的变量值的拷贝,造成数据的不一致。 要解决这个问题,就需要把变量声明为volatile,这就指示 JVM,这个变量是共享且不稳定的,每次使用它都到主..

qq_411664740的博客 131

Java多线程并发编程实战深入解析synchronized与volatile关键字的工作原理与应用场景

synchronized还保证可见性和有序性,因为线程在释放锁时会强制将工作内存中的修改刷新到主内存,而在获取锁时会清空工作内存并从主内存重新加载变量。当一个变量被声明为volatile时,任何线程对该变量的写操作都会立即刷新到主内存,且读操作会直接从主内存读取最新值。synchronized适用于需要原子性操作的场景,例如对共享资源的复合操作(如银行转账、计数器递增等)。stop))、单例模式的双重检查锁(结合volatile修饰实例变量),以及读写锁的轻量级替代方案(如仅需保证写入立即对读线程可见)。

fanglei10的专栏 405

Java并发三要素:原子性、可见性、有序性

解决的是操作是否完整执行的问题(防止中途被干扰)。解决的是修改后的值是否及时被其他线程看到的问题(防止读取到过期值)。解决的是代码执行顺序是否符合预期的问题(防止指令重排序导致的逻辑错误)。这三者共同构成了 Java 内存模型 (JMM) 的核心规则,用于规范多线程环境下共享变量的访问行为。和volatile是实现这三大特性的关键机制,而包则提供了更高级别的抽象来简化并发编程。理解并正确运用这些概念是编写健壮并发代码的基础。

fegfsf的博客 678
上一篇: Java锁Synchronized不同用法的区别
下一篇: Java常用锁的使用
ArtisticProgramming
博客等级 码龄8年 1粉丝 6原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值