【Java 快速复习】 Java 内存模型 并发问题本质
创始人
2024-03-27 16:35:09
0

【Java 快速复习】 Java 内存模型 & 并发问题本质

在 Java 领域,我们经常会说两个名词大家要有所区分:

  1. JVM 内存模型:这个所说的是 JVM 内存的划分规则,如 堆、栈、元空间等
  2. Java 内存模型:这个所说的是线程和主内存之间,以及 CPU 高速缓存和内存之间的抽象关系,,这种抽象关系带来的就是 Java 并发问题,Java 内存模型规范了 JVM 如何提供按需禁用缓存和编译优化的方法。具体来说,这些方法包括 volatile、synchronized 和 final 三个关键字

并发问题源头

主要是三个问题:

  1. 缓存带来的可见性问题。
  2. 编译优化带来的有序性问题。
  3. 线程切换带来的原子性问题 (Java 语言分解成 CPU 指令操作并不是原子)。

可见性

多核 CPU 缓存(寄存器) 和 内存间存在可见性问题

A 线程 使用 CPU-1 读取内存中变量 X = 1 ;

B 线程 使用 CPU-2 读取内存中变量 X = 1;

A B 线程操作变量都是在本核 CPU 缓存中执行操作,最后写回。这个操作过程对于 A B 两线程是不可见的。

在这里插入图片描述

这就是可见性问题,解决该问题即,禁用 CPU 缓存,Java 中 volatile 关键字

有序性

Java 程序在编译过程中为了优化性能,有时会改变程序中语句的先后顺序

int a = 1;
int b = 2;

优化后可能为

int b = 2;
int a = 1;

这类优化调整了语句的顺序但不影响程序的最终结果。

其实我们在聊有序性的时候,最有可能遇到的问题是单例初始化时的双重检查。下面是一个比较常见的双重检查获取单例对象的代码

public class Singleton {static Singleton instance;static Singleton getInstance(){if (instance == null) {synchronized(Singleton.class) {if (instance == null)instance = new Singleton();}}return instance;}
}

这个 getInstance() 方法看上去没有什么问题,但在指令重排后就有可能引发并发问题。

我们认为的 instance 赋值过程是

  1. 划分一块内存 M
  2. 在 M 中初始化 Singleton 对象
  3. 将 M 内存地址赋值给 instance 变量

而实际指令重排后

  1. 划分一块内存 M
  2. 将 M 内存地址赋值给 instance 变量
  3. 在 M 中初始化 Singleton 对象

这会导致在第二步的时候 instance 变量就不为 null 了,但此时对象还未初始化,如果多线程调用就可能返回一个未初始化的对象,从而导致程序错误。

同样的解决该问题的方法就是禁用指令重排,在 Java 中使用 volatile 关键字

原子性

CPU 能够保证的原子操作是 CPU 指令级别的,而一个 Java 语句可能会对应多个 CPU 指令,这就导致 Java 的单个语句可能并不是原子的,在线程切换的时候就可能出现并发问题,所以需要我们在 Java 语言的级别保证某些操作的原子性。

比如执行一个 +1 的操作

int count = 0;
void addOne(){count++;
}

如果有多个线程同时调用 addOne() 方法,这个最终的总数是不准确的。

对于 ++ 操作拆解成 CPU 指令至少需要三条:

  1. 将 count 变量加载到 CPU 寄存器
  2. 在寄存器中执行 +1 操作
  3. 将结果写回内存

在这个流程中多个线程同时调用 addOne 方法,线程 A 读取 count 值为 0,线程 B 读取 count 值也是 0

线程 A 执行完毕写回内存 count 值为 1,线程 B 执行完毕写回内存 count 值也为 1。我们期望这个值应该为 2 。

看上去似乎是可见性的问题 volatile 关键字修饰后能否解决这个问题。

其实是不能的,volatile 能解决一部分问题,它解决不了线程切换的问题。需要通过互斥锁来解决,在 Java 中即 synchronized

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
客厅放八骏马摆件可以吗(家里摆... 今天给各位分享客厅放八骏马摆件可以吗的知识,其中也会对家里摆八骏马摆件好吗进行解释,如果能碰巧解决你...
苏州离哪个飞机场近(苏州离哪个... 本篇文章极速百科小编给大家谈谈苏州离哪个飞机场近,以及苏州离哪个飞机场近点对应的知识点,希望对各位有...