Java并发编程—volatile

news2024/11/8 19:50:27

文章目录

  • volatile的应用
  • volatile的定义与实现原理
    • 专业术语:
    • volatile是如何来保证可见性的呢?
  • volatile的原理:
    • volatile的两条实现原则:(物理上如何实施)
  • volatile的内存语义
    • volatile的特性
    • 例:下面这个,为什么能保障读的安全?
  • volatile写-读的内存语义
    • 为什么volatile有写后读还是不是线程安全的?

——————————————————————————

volatile的应用

volatile可以修饰变量
并发编程中有两种锁:

  • synchronized
  • volatile

volatile:

  • volatile是轻量级的 synchronized
  • volatile锁住的时候可以写,是只保证读是正确的

volatile在多处理器开发中保证了共享变量的“可见性” :

  • 可见性:当一个线程 修改一个共享变量时,另外一个线程能读到这个修改的值。
  • 因此能保证读到的值是正确的
  • 可见性一定是在多线程的情况下,一个线程对变量进行了修改,其他线程能立刻知道
  • 每个线程对变量进行操作的时候都会拷贝一个副本数据

线程不安全是因为t1,t2,t3操作变量s时都会拷贝一份s副本,彼此不知道,t1给s+1,t2给s+2,t1先更新数据,t2后更新数据,这时cpu的s=2,而不是正确的3,这样线程不安全,可见性是指t1对变量s进行操作之后,t2,t3等其他变量拷贝的s的数据就会失效,需要再读一次s的数据,这样读到的数据就是新修改的数据。

  • volatile修饰符使用恰当的话,比synchronized的使用和执行成本更低,因为volatile功能更少,它不会增加线程上下文的切换和调度,速度更快。
  • cpu分配时间片的时候,volatile不会浪费掉

volatile的定义与实现原理

  • volatile的用法就是修饰变量,声明一个变量然后用它修饰,多线程调用这个变量,其他不用改Java编程语言允许线程访问共享变量
  • 共享变量指多线程指向同一个地址(一般是引用类型)

专业术语:

在这里插入图片描述

  1. 内存屏障:是一个约定,访问变量的时候先访问屏障看状态,例:如果是0就访问变量,如果是1就不访问变量
  2. 缓存行:(缓冲行)
    在这里插入图片描述
    高速缓存里面也是分成一份一份的,分成若干缓存行
  3. 原子操作: 指一系列操作要么都成功,要么都失败,要是一系列操作有5个步骤,前四个成功,最后一个失败,那么前四个都会还原
  4. 缓存行填充:让自己霸占缓存行,总线传数据的时候就不容易阻塞
    • 缓存的概念:(什么叫做缓存)把数据存到一个离使用者更近的区域,让使用者访问更快
    • 缓存有一个特点,就是存储容量比较小,价格也更贵,所以存储到缓存的数据都是访问频率更高的
    • 缓存中的数据都有滞后性,需要隔一段时间更新一次
      在这里插入图片描述
  5. 缓存命中:这里和操作系统的缓存不一样
    cpu从内存读数据也很慢,所以cpu内部有高速缓存,cpu读取数据的时候先在高速缓存查看数据,如果有数据就叫做缓存命中。
  6. 写命中:cpu如果在高速缓存找到了目标的变量,对变量进行了写操作,就叫做写命中。
  7. 写缺失:一个有效的缓存行被写入到不存在的内存区域。缓存中写操作后的变量要刷新到内存的,写缺失是因为在多线程里,t1和t2对同一个变量进行操作,t1进行写操作后,从高速缓存刷新到内存之前,t2把变量删除了,导致写操作后的变量无法存入内存,就是写缺失。

volatile是如何来保证可见性的呢?

1)将当前处理器缓存行的数据写回到系统内存。
2)这个写回内存的操作会使在其他CPU里缓存了该内存地址的数据无效。

  • 为了提高处理速度,处理器不直接和内存进行通信,而是先将系统内存的数据读到内部缓存(L1,L2或其他)后再进行操作,但操作完不知道何时会写到内存。
  • 如果对声明了volatile的 变量进行写操作,JVM就会向处理器发送一条Lock前缀的指令,将这个变量所在缓存行的数据 写回到系统内存。
  • 但是,就算写回到内存,如果其他处理器缓存的值还是旧的,再执行计算操 作就会有问题。
  • 所以,在多处理器下,为了保证各个处理器的缓存是一致的,就会实现缓存一致性协议,每个处理器通过嗅探在总线上传播的数据来检查自己缓存的值是不是过期了,当处理器发现自己缓存行对应的内存地址被修改,就会将当前处理器的缓存行设置成无效状态,当处理器对这个数据进行修改操作的时候,会重新从系统内存中把数据读到处理器缓存里。

volatile的原理:

volatile的两条实现原则:(物理上如何实施)

cpu三个核,理论上三个线程可以同时运行,不会存在三个线程同时在内存刷新同一个数据的情况,因为操作内存一定是需要排队的,一个内存在一个时刻只能有一个线程操作
1)Lock前缀指令会引起处理器缓存回写到内存。
2)一个处理器的缓存回写到内存会导致其他处理器的缓存无效。

  • 总线是指令级别的排队,加入t1线程有20个指令,t2线程有10个指令,排队情况可能是t1的指令1—t2的指令1——t2的指令2…
  • 锁总线是一个线程的全部指令执行完毕后总线才会释放,否则其他线程只能等待
  • 锁总线代价很大

即,volatile在往内存写的时候有两种方案:锁总线、锁缓存

volatile的内存语义

前面讲的是volatile如何去使用,这里讲的是volatile里面是怎么实现的(理论依据)
前面的volatile操作是为了实现这些理论

volatile的特性

  • volatile只能保障读是正确的,并不能保障多线程下的安全。
  • volatile底层虽然也用了lock锁,所以volatile也是一种锁,但是不保证线程安全,即便是加了synchronized重锁,也不一定是线程安全的,保障了写后读才能保障多线程下的安全。
  • volatile还能防止指令重排序,volatile修饰的变量,使用的时候,它的前后凡是涉及到写后读的是不能重排序的
    要想保证并发安全,有且只能有写后读操作
    在这里插入图片描述

例:下面这个,为什么能保障读的安全?

  • 因为加锁之后,释放锁之后其他线程才能操作这个数据,写的时候不能读,读的时候不能写,不存在正在写的时候读(不会正在写的时候读),因此读的一定是正确的;
    例:set get get get set get get set set get get get—》任何一个读操作都能看到最后一次写操作
    上面这个,
    volatile在这种情况下只能保障读是正确的,但这并不是volatile的全部功能

volatile写-读的内存语义

为什么volatile有写后读还是不是线程安全的?

因为—>要想保证并发安全,有且只能有写后读操作

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

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

相关文章

SpringBoot -集成Druid

文章目录Druid概述使用问题解决Spring监控不生效方式1:修改yml的配置写法方式2:参考DruidSpringAopConfiguration自行注入Bean,灵活(更建议)Druid 概述 官网: https://github.com/alibaba/druid   文档&a…

校园论坛(Java)—— 用户管理系统模块

校园论坛(Java)—— 用户管理系统模块 文章目录校园论坛(Java)—— 用户管理系统模块[toc]1、写在前面2、系统结构设计2.1 各个页面之间的调用关系2.2. 用户管理系统模块各层的设计3、管理员管理用户功能3.1 管理员查看普通用户的…

微服务框架 SpringCloud微服务架构 10 使用Docker 10.1 镜像命令

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式,系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 SpringCloud微服务架构 文章目录微服务框架SpringCloud微服务架构10 使用Docker10.1 镜像命令10.1.1 镜像相关命令10.1.2 镜像操作命令10.1.…

SpringBoot_整合PageHelper

分页插件/PageHelper插件 我们在正常的查询业务之中,只需要加上一行代码就可以实现分页的数据的封装处理 实现原理 PageHelper方法使用了静态的ThreadLocal参数,分页参数和线程是绑定的。内部流程是ThreadLocal中设置了分页参数(pageIndex&#xff0c…

TypeScript21(装饰器Decorator)

Decorator 装饰器是一项实验性特性,在未来的版本中可能会发生改变 不仅增加了代码的可读性,清晰地表达了意图,而且提供一种方便的手段,增加或修改类的功能; 若要启用实验性的装饰器特性,你必须在命令行或…

计算机网络 HTTPS

HTTPS HTTPS (全称:Hypertext Transfer Protocol Secure ),是以安全为目标的 HTTP 通道,在HTTP的基础上通过传输加密和身份认证保证了传输过程的安全性 。HTTPS 在HTTP 的基础下加入SSL,HTTPS 的安全基础是…

git:多分支管理

多分支管理1. 列出分支2. 新建分支3. 删除分支4. 切换分支5. 分支合并多分支开发的特点 | 作用1. 测试:合并之后再在分支中工作是否主分支里面的相同文件不会更改2. 测试:修改编辑test分支的文件,最后再合并分支,是否是直接覆盖&a…

FT2004(D2000)开发实战之启动流程介绍

一 启动流程概述 飞腾FT2004/D2000芯片提供两种引导方案,具体如下所示: 方案一: 方案二: 方案一和方案二的区别是第二阶段的运行组件不同,方案一运行的是U-boot、方案二运行的是UEFI 那么为什么会这样的了? 答案是:飞腾FT2004/D2000芯片既可以用于嵌入式方案,也可以…

Docker中网络的使用和配置用法详解

一、单个物理机中docker网络 1.1 Docker默认网桥 安装Docker 服务默认会创建一个 docker0 网桥(其上有一个 docker0 内部接口),它在内核层连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络。 使用 doc…

初识猿如意开发工具

嗨,大家好,我是异星球的小怪同志 一个想法有点乱七八糟的小怪 如果觉得对你有帮助,请支持一波。 希望未来可以一起学习交流。 一、初遇猿如意 第一次听说猿如意开发工具,于是抱着试试的心态,开始下载尝试。 首先是…

算法导论23章最小生成树习题—23.2练习

23.2-1对于同一个输人图,Kruskal 算法返回的最小生成树可以不同。这种不同来源于对边进行排序时,对权重相同的边进行的不同处理。证明:对于图G的每棵最小生成树T,都存在一种办法来对G的边进行排序,使得Kruskal算法所返回的最小生成…

HTML+CSS+JS网页设计期末课程大作业——上海旅游景点(10页)web前端开发技术 web课程设计 网页规划与设计

👨‍🎓学生HTML静态网页基础水平制作👩‍🎓,页面排版干净简洁。使用HTMLCSS页面布局设计,web大学生网页设计作业源码,这是一个不错的旅游网页制作,画面精明,排版整洁,内容…

离散化【带题讲解】

全文目录🤔 原理😕 区间和😵‍💫 建立映射😵‍💫 查找映射的下标😵‍💫 代码🤔 原理 离散化,把无限空间中有限的个体映射到有限的空间中去,以此提…

NVIDIA 安装 CUDA

名词解释:CUDA 是一个架构 该架构使GPU能够解决复杂的计算问题 此实战使用电脑为联想Y9000P 显卡型号为 3060 在安装 CUDA 之前需要先打开 NVIDIA 控制面板 一、准备工作 如图我这个显卡需要安装 CUDA 11.7 的版本 二、下载软件 进入官网下载 CUDA NVIDIA Deve…

解放军军官军衔(不含士兵军衔)分为3等10级

军衔,是国家最高权力机关授予军人的一种衔称。不同的级别有不同的军衔。对于军衔的认识,一些朋友或许只有片面的认识,下面,笔者就给大家来科普一下中国的军衔。 为了纪念中国人民解放军建军93周年,弘扬爱国主义精神&a…

被迫毕业,面试 30 家公司,终于上岸了!

大家好,我是君哥。今天分享一个老弟,被“毕业”后的求职经历。 在老东家干了 6 年,发展一般,很想出去,但是一直没有合适的机会,只好一边准备面试一边学习。让我没有想到的是,突然收到了“毕业”…

(1-线性回归问题)线性回归(Linear regression)Lasso回归和Ridge回归的区别

回归分析是机器学习中的经典算法之一,用途广泛,在用实际数据进行分析时,可能会遇到以下两种问题 过拟合, overfitting欠拟合, underfitting 在机器学习中,首先根据一批数据集来构建一个回归模型,然后在用另外一批数据…

Vue 中 (moment)操作日期的加减与展示

目录 基本语法 : 展示效果如下: 使用方式: 1、首先在 pacaage.json 中引入依赖 "moment": "^2.29.4" 2、然后命令行 install 安装 : 3、最后,在使用的页面引入moment 4、data 中我定义了一个…

python的Django项目中常见命令以及常错点(Linux环境下)

USE 数据库名 --------------- 切换数据库更新virtualenv库(用于创建虚拟环境):sudo pip install -U virtualenv创建虚拟环境:virtualenv -p python venv(虚拟环境的目录名)激活虚拟环境:source venv/b…

利用Python处理excel表格,panda合并表格、合并多个excel、多个sheet

前言 记录一下,在使用pandas处理excel表格表格时候,关于分割(切分)表格这一块儿的操作。 这个系列会有三篇左右文章,这是第二篇,excel表格合并 我们常说的 excel文件, 在广义上,是指以 xls 或 xlsx 为后缀…