当前位置: 首页 > article >正文

Java-并发编程及Volatile关键字详解

结论:并发编程三个概念:原子性、可见性、有序性,volatile可保证线程间的可见性和部分有序性

1.原子性(volatile并不能保证原子性)

一个或多个操作,要么全部执行,要么全不执行,执行期间不会被打断
原子性是拒绝多线程操作的,不论是单核还是多核,对于原子性的量,同一时刻只允许一个线程对其进行操作,执行期间不会被线程调度器打断的操作,都可以认为是原子性操作。类似a=1的赋值操作为”原子性”操作,而a++就不是(实际上是1、读取a的值,2、赋值操作,3、将值刷回主存)

2.可见性

当多个线程对于同一个变量进行操作时,一个线程对于操作的结果会被其他线程立刻感知到。
多线程情境下,一个线程对共享变量的操作其他线程是不可见的。Java使用Volatile来保证可见性,一个线程在本地内存中对共享变量修改后会强制更新到主存中,同
时其他线程中的变量副本变为无效状态,直接从主存中读取。当然使用synchronized和lock也可以达到可见性。 解释: i=1; i++; 线程A读取i的值,在缓存区进行+1操作,还未刷新到主存; 此时切换到线程B,因为i的值还未改变,所以B正常进行+1计算;
现在时间片分配给A,A将i=2刷新到主存,线程B中的i副本重新从主存读取,但是并不会影响原来i+1之后的结果,最后B将i计算的结果2刷新到主存;这样就导致了异常,主要原因还是i++并非原子性操作。

3.有序性

程序的执行顺序按照代码的先后顺序来执行。
Java内存模型(JMM)中的有序性可以总结为:如果在本线程中观察,所有的操作都是有序的;如果在一个线程中观察另一个线程,所有操作都是无序的。
JMM为了效率允许编译器和处理器对指令进行重排序,不会影响单线程的运行结果,但是对多线程会有影响。
Volatile只保证可见性,不保证原子性。(线程A修改后将其同步到主存,线程B、C本地内存中的变量失效,此时B、C去主存获取后在线程本地内存并发进行操作,然后同步到主存,此时就会有问题。)
Volatile: 可保证可见性和部分有序性,作用类似于内存屏障。 int a = 1; // float d = 2.3; boolean
b = false; // volatile 修饰 :相当于内存屏障 double c = 2.0;
对于上面的代码,并不相互依赖、影响,在编译的时候可能会被重排序。这样就不一定会按照代码顺序来执行了。若b被volatile修饰,那么a,d一定会在b之前执行(但因为a、d相互不影响,所以a、d可能会被重排序),c一定会在b之后执行。


http://www.kler.cn/a/298264.html

相关文章:

  • 【LabVIEW学习篇 - 16】:文件操作
  • C语言俄罗斯方块(VS2022版)
  • 数据库——MySQL概述
  • 基于SA模拟退火算法的多车辆TSP问题求解matlab仿真
  • 学习threejs,创建内置几何体,并加入旋转动画
  • 【AIStarter:AI绘画、设计、对话】零基础入门:Llama 3.1 + 千问2快速部署
  • 【重点】(非常全) Node.js的生态有哪些包
  • 2025毕业设计免费指导!!
  • Linux是如何收发网络包的
  • mysql主从复制搭建
  • linux 文件压缩并且切割压缩
  • Mysql基础练习题 1407.排名靠前的旅行者(力扣)
  • 开源DDOS防火墙 零成本搭建DDOS防御
  • JavaWeb【day12】--(SpringBootWeb登录认证)
  • C++学习笔记(14)
  • 无人机动力系统设计之桨叶推力计算
  • 在Webmin上默认状态无法正常显示 Mariadb V11.02及以上版本
  • 企业财税自动化解决方案与其他财务软件的集成与应用
  • 直播相关02-录制麦克风声音,QT 信号与槽,自定义信号和槽
  • 2024网络安全学习路线,最全保姆级教程,学完直接拿捏!