JAVA并发编程(1)——(概念注意事项,核心问题-可见性,原子性,有序性,volatile关键字)
创始人
2025-05-30 05:27:55
0

java并发编程

  • java并发编程
      • 1.1 并行与并发
      • 1.2 多线程
      • 1.3 多线程优点
      • 1.4 多线程问题
      • 1.5 (JMM)java内存模型
    • 并发编程核心问题--可见性,原子性,有序性
      • 2.1 可见性
      • 2.2 原子性
      • 2.3 有序性
    • volatile 关键字

java并发编程

1.1 并行与并发

单核 cpu 下,线程实际是串行执行的。操作系统中有一个组件叫做任务调 度器,将 cpu 的时间片,分给不同的线程使用,只是由于 cpu 在线程间(时间片 很短)的切换非常快,人类感觉是同时运行的。 总结为一句话就是:微观串行,宏观并行,一般会将这种线程轮流使用 cpu 的做法称为并发,concurrent.

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XdfvBUuw-1679140400987)(C:\Users\封纪元\AppData\Roaming\Typora\typora-user-images\1642639138705.png)]

多核 cpu 下,每个核(core)都可以调度运行线程,这时候线程可以是并 行的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UxcjX0ls-1679140400989)(C:\Users\封纪元\AppData\Roaming\Typora\typora-user-images\1642639168772.png)]

例:

大家排队在一个咖啡机上接咖啡,交替执行,是并发;两台咖啡机上面接咖啡, 是并行。

从严格意义上来说,并行的多任务是真的同时执行,而对于并发来说,这个过程 只是交替的,一会执行 任务 A,一会执行任务 B,系统会不停地在两者之间切 换。

并发说的是在一个时间段内,多件事情在这个时间段内交替执行

并行说的是多件事情在同一个时刻同事发生。

1.2 多线程

Java 是最先支持多线程的开发的语言之一,

Java 从一开始就支持了多线程 能力。由于现在的 CPU 已经多是多核处理器了,是可以同时执行多个线程的.

1.3 多线程优点

多线程技术使程序的响应速度更快 ,可以在进行其它工作的同时一直处于活动

状态,程序性能得到提升.

性能提升的本质 就是榨取硬件的剩余价值(硬件利用率).

1.4 多线程问题

多线程带来的问题是什么?

安全性(访问共享变量),性能(切换开销等)

1.5 (JMM)java内存模型

问题

硬件的发展中,一直存在一个矛盾,CPU、内存、I/O 设备的速度差异。

速度排序:CPU > 内存 > I/O 设备

为了平衡这三者的速度差异,做了如下优化:

  • CPU 增加了缓存,以均衡内存与 CPU 的速度差异;
  • 操作系统以线程分时复用 CPU,进而均衡 I/O 设备与 CPU 的速度差异;
  • 编译程序优化指令执行次序,使得缓存能够得到更加合理地利用

JMM

​ Java 内存模型(Java Memory Model,JMM)规范了 Java 虚拟机与计算 机内存是如何协同工作的。Java 虚拟机是一个完整的计算机的一个模型,因此这个模型自然也包含一个内存模型——又称为 Java 内存模型

​ Java 内存模型,用于屏蔽掉各种硬件和操作系统的内存访问差异,以实现 让 Java 程序在各种平台下都能达到一致的并发效果,JMM 规范了 Java 虚拟机 与计算机内存是如何协同工作,规定了一个线程如何以及何时可以看到由其他线 程修改过后的共享变量的值,以及在必须时如何同步的访问共享变量。

计算机在高速的 CPU 和相对低速的存储设备之间使用高速缓存,作为内存 和处理器之间的缓冲。将运算需要使用到的数据复制到缓存中,让运算能快速运 行,当运算结束后再从缓存同步回内存之中

​ 在多处理器的系统中(或者单处理器多核的系统),每个处理器内核都有自己 的高速缓存,它们有共享同一主内存(Main Memory)。

当多个处理器的运算任务都涉及同一块主内存区域时,将可能导致各自的缓存数据不一致。

JVM 主内存与工作内存

Java 内存模型的主要目标是定义程序中各个变量的访问规则,**即在虚拟机 中将变量(线程共享的变量)存储到内存和从内存中取出变量这样底层细节**。 **Java 内存模型中规定了所有的变量都存储在主内存中,每条线程还有自己的工 作内存**,**线程对变量的所有操作都必须在工作内存中进行**,**而不能直接读写主内 存中的变量**。 这里的工作内存是 JMM 的一个**抽象概念**,也叫本地内存**,其存储了该线程以 读 / 写共享变量的副本**。 

就像每个处理器内核拥有私有的高速缓存,JMM 中每个线程拥有私有的本地内存。

不同线程之间无法直接访问对方工作内存中的变量,线程间的通信一般有两种方 式进行,一是通过消息传递,二是共享内存。Java 线程间的通信采用的是共享 内存方式,线程、主内存和工作内存的交互关系如下图所示:

在这里插入图片描述

这里所讲的主内存、工作内存与 Java 内存区域中的 Java 堆、栈、方法区 等并不是同一个层次的内存划分,这两者基本上是没有关系的**,如果两者一定要 勉强对应起来,那从变量、主内存、工作内存的定义来看,主内存主要对应于 Java 堆中的对象实例数据部分,而工作内存则对应于虚拟机栈中的部分区域**。

并发编程核心问题–可见性,原子性,有序性

2.1 可见性

一个线程对共享变量的修改,另外一个线程能够立刻看到,我们称为可见性对于如今的多核处理器,每颗 CPU 都有自己的缓存,而缓存仅仅对它所在 的处理器可见,CPU 缓存与内存的数据不容易保证一致。 为了避免处理器停顿下来等待向内存写入数据而产生的延迟,处理器使用写 缓冲区来临时保存向内存写入的数据。写缓冲区合并对同一内存地址的多次写, 并以批处理的方式刷新也就是说写缓冲区不会即时将数据刷新到主内存中

缓存不能及时刷新导致了可见性问题。

举例

假设线程 1 和线程 2 同时开始执行,那么第一次都会将 a=0 读到各自的 CPU 缓存里,线程 1 执行 a++之后 a=1,但是此时线程 2 是看不到线程 1 中 a 的值的,所以线程 2 里 a=0,执行 a++后 a=1。 线程 1 和线程 2 各自 CPU 缓存里的值都是 1,之后线程 1 和线程 2 都会将 自己缓存中的 a=1 写入内存,导致内存中 a=1,而不是我们期望的 2。
在这里插入图片描述

2.2 原子性

线程切换带来的原子性问题

​ 原子的意思代表着——“不可分”; 一个或多个操作在 CPU 执行的过程中不被中断的特性,我们称为原子性. 原子性是拒绝多线程交叉操作的,不论是多核还是单核,具有原子性的量,同一 时刻只能有一个线程来对它进行操作. CPU 能保证的原子操作是 CPU 指令级别的,而不是高级语言的操作符。线程切换导致了原子性问题

在这里插入图片描述

Java 并发程序都是基于多线程的,自然也会涉及到任务切换,任务切换的 时机大多数是在时间片结束的时候。我们现在基本都使用高级语言编程,高级语 言里一条语句往往需要多条 CPU 指令完成。如 count++,至少需要三条 CPU 指令

指令 1:首先,需要把变量 count 从内存加载到工作内存;

指令 2:之后,在工作内存执行 +1 操作;

指令 3:最后,将结果写入内存;

还是以上面的 count++ 为例。两个线程 A 和 B 同时执行 count++, 即便 count 使用 volatile 修辞,我们预期的结果值是 2,但实际可能是 1。

在这里插入图片描述

2.3 有序性

有序性指的是程序按照代码的先后顺序执行。 编译器为了优化性能,有时候会改变程序中语句的先后顺序。
在这里插入图片描述

例子:

在这里插入图片描述

​ init(); 与 inited = true; 并没有数据的依赖**,在单线程看来,如果把两句的代 码调换好像也不会出现问题。**

但此时处于一个多线程的环境,而处理器真的把这两句代码重新排序,那问题就 出现了,若线程 1 先执行 inited = true; 此时,init() 并没有执行,线程 2 就 已经开始调用 work() 方法,此时很可能造成一些奔溃或其他问题的出现Java 内存模型中,允许编译器和处理器对指令进行重排序,但是重排序过程不 会影响到单线程程序的执行,却会影响到多线程并发执行的正确性.

总结

缓存导致的可见性问题线程切换带来的原子性问题编译优化带来的有序性问题其实缓存、线程、编译优化的目的和我们写并发程序的目的是相同的, 都是提高程序安全性和性能。但是技术在解决一个问题的同时,必然会带来另外 一个问题,所以在采用一项技术的同时,一定要清楚它带来的问题是什么,以及如何规避

volatile 关键字

一旦一个共享变量(类的成员变量、类的静态成员变量)被 volatile 修饰之后:

  1. 保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变 量的值,这新值对其他线程来说是立即可见的。
  2. 禁止进行指令重排序
  3. volatile 不能保证对变量操作的原子性

一个代码实例:

package concurrentProgrammer.volatiledemo;public class ThreadDemo implements  Runnable{/*volatile 修饰的变量,在一个线程中被修改后,对其它线程立即可见禁止cpu对指令重排序*/private volatile   boolean flag = false;//共享数据@Overridepublic void run() {try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}this.flag = true;//让一个线程修改共享变量值System.out.println(this.flag);}public boolean getFlag() {return flag;}public void setFlag(boolean flag) {this.flag = flag;}
}

测试:

package concurrentProgrammer.volatiledemo;public class TestVolatile {public static void main(String[] args) {ThreadDemo td = new ThreadDemo();Thread t = new Thread(td);//创建线程t.start();//main线程中也需要使用flag变量while(true){if(td.getFlag()){System.out.println("main---------------");break;}}}
}

结果:

在这里插入图片描述

不加volatile关键字结果:

在这里插入图片描述

程序一直在运行

相关内容

热门资讯

试题28 基础练习 回形取数 问题描述   回形取数就是沿矩阵的边取数,若当前方向上无数可取或已经取过,...
最新或2023(历届)北京昌平... 昌平区新增、改扩建中小学今年昌平区将新增、改扩建一批幼儿园、中小学,并增加幼儿园和小学入学学位,名校...
递归算法 - 分治算法 分治算法简介 分治算法(divide and conquer)是一种递归...
最新或2023(历届)北京丰台... 丰台区今年引进十余所优质校分校今年,丰台区将新增小学优质资源学位1100个,中学新增510个。记者从...
最新或2023(历届)北京通州... 通州区  3名校年内开建通州校区通州区三名小年内开间通州校区,它们分别为北京五中、景山学校、首师大附...
广州市教育局小升初民校必须面谈...  备受关注的最新或2023(历届)广州小升初新政细则至今不出台,民办学校“禁笔试改面谈”后如何面谈,...
SAP 发出商品业务配置 SAP发出商品业务配置,即: 出具销售发票时结转成本  一、业务背景&#...
最新或2023(历届)成都小升... 小升初政策 3月公布最新或2023(历届)小升初政策拟于3月公布,学生可通过就读小学、户籍所在地的区...
最新或2023(历届)广州小升... 最新或2023(历届)开始民校招生全面推行面谈关键词面谈 小学成绩 面谈名额相关政策:根据最新或20...
最新或2023(历届)成都小升... 最新或2023(历届)小升初政策拟于3月公布,学生可通过就读小学、户籍所在地的区(市)县教育行政部门...
最新或2023(历届)广州小升...  最新或2023(历届)广州小升初政策面临5大变革  最新或2023(历届),广州小升初的新政层出不...
最新或2023(历届)北京六城... 最新或2023(历届)北京六城区全部小升初学校生源质量排名表】:
【CNN】DenseNet——... DenseNet论文名称:Densely Connected Convolutiona...
AAAI顶会行人重识别算法源码... 数据及代码链接见文末 1.项目配置与数据集介绍 在这里我们使用的是清华大学的行人重识...
最新或2023(历届)昆明民办... 本报讯记者张丽亚报道昨日,昆明市教育局对外公布关于做好最新或2023(历届)民办初中招生工作的通知,...
最新或2023(历届)佛山小升... 佛山电台 佛山实验学校集团旗下4所学校,在全市率先公布明年“小升初”面谈方案。佛山实验学...
最新或2023(历届)广州小升... 小升初变革对学生提出了新要求。 (资料照片)第五届“华南金质教育品牌机构”评选结果揭晓 8家主流机构...
最新或2023(历届)昆明小升...   今年7月5日,小升初考试结束后,一名考生在演算题目。本报记者 刘筱庆 摄  明年昆明的小升初问题...
最新或2023(历届)佛山民办... 佛山实验学校集团旗下三学校发布的这份方案中把5%的“就近范围”定为“禅城区”引发市民质疑明年是佛山民...
烟气监测数据转IEC104规约... 1项目需求 项目背景:国能赤峰生物发电公司环保数据已经接入环保数采仪,通...