什么是并发 ?

在单核CPU下, 线程是串行执行的 ,由于cpu特别快, 给人的感觉像是同时执行的(操作系统中有一个组件叫任务调度器 , 它会将CPU的时间片分给不同的线程, CPU在这些线程中不断切换), 微观上是串行的 , 宏观上看起来是并行的 , 一般我们将线程轮流使用CPU的做法叫做并发

在多核CPU下, 线程是可以并行的, 现在的计算机几乎都是多核的, 每个核都会调度线程,如下图

并行和并发

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

并发说的是在一个时间段内,多件事情在这个时间段内交替执行。(某个时刻只做某一件事)

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

多线程

现在的CPU都是多核的, 采用多线程的方式, 可以提高程序的响应速度, 榨取硬件的剩余价值(提高CPU利用率), 同时执行多个线程

但是多线程也会带来一些问题, 例如安全性: 多个线程共享同一变量等 , 性能问题 : 切换线程产生的性能开销等, 当然这些问题都有对应的解决方案

Java内存模型(JMM)

先提出问题 : 我们知道, 在硬件的发展中, CPU , 内存 , I/O设备速度存在差异, CPU>内存>I/O
为了平衡这几者之间的差异, 做了如下优化 :

CPU 增加了缓存,以均衡内存与 CPU 的速度差异;

操作系统以线程分时复用 CPU,进而均衡 I/O 设备与 CPU 的速度差异;

编译程序优化指令执行次序,使得缓存能够得到更加合理地利用。

所以在此之上, java内存模型(JMM)就规范了java虚拟机如何来跟计算机内存协调工作 , JMM可以忽略掉硬件与操作系统的内存访问差异 , 它规定了一个线程何时能看到由其他线程修改过的共享变量的值, 以及如何同步的访问共享变量

Java 内存模型的主要目标是定义程序中各个变量的访问规则,即在虚拟机中将变量(线程共享的变量)存储到内存和从内存中取出变量这样底层细节

主内存与工作内存

JMM规定了所有的变量都必须存在主内存中, 每条线程都有自己的工作内存, 对变量进行操作必须在自己的工作内存中进行, 不能直接去读写主内存中的变量(这里的工作内存是 JMM 的一个抽象概念,也叫本地内存,其存储了该线程以读 / 写共享变量的副本。)

不同线程之间无法直接访问对方工作内存中的变量,线程间的通信一般有两种方式进行,一是通过消息传递,二是共享内存。Java 线程间的通信采用的是共享内存方式

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