前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java内存模型

Java内存模型

作者头像
shysh95
发布2021-03-16 11:20:12
3730
发布2021-03-16 11:20:12
举报
文章被收录于专栏:shysh95

Java内存模型我们大致会分为两篇来讲,主要解决一下问题:

  1. 为什么需要并发处理
  2. CPU高速缓存
  3. 缓存一致性
  4. 什么是内存模型
  5. Java主内存和工作内存交互协议(原子性)
  6. Java内存模型-可见性
  7. Java内存模型-有序性

第6条和第7条我放在下一篇讲,话不多说,一起掀开Java高并发内容的第一章。

1. 为什么需要并发处理

1.1 提升性能

1.1.1 提升CPU的使用效率

目前计算机上会有多个CPU核心,我们可以创建多个线程,操作系统会将线程分配各不同的CPU去执行,如果只有一个线程,那么只会有一个CPU去工作,其他的CPU将会被浪费。

计算机CPU的运算速度相较于I/O等子系统的速度快太多,假设我们使用单线程做一个I/O操作,此时由于I/O操作缓慢导致线程被阻塞,即时有CPU处于空闲状态,I/O操作后面的指令也无法被执行。但是如果使用多线程的话,我们可以使用一个线程去做I/O操作,I/O操作后面的指令可以使用另一个线程交给空闲的CPU去执行。

1.1.2 降低系统响应时间

TPS:每秒事务处理数,它代表着一秒内服务段平均能响应的请求总数。

假设我们的WEB服务器同时有10个用户访问(每个响应大约需要1s),如果使用单线程,后面的9个用户则需要等待,如果一个用户很不幸是第10个,那么他将会需要等待10s以上,用户体验将会非常差。但是使用多线程则可以回避响应时间过长的问题,每个用户都能尽快得到响应。

当然目前WEB服务器除了使用多线程处理以外,还会部署多台,部署多台的好处除了可以提高我们网站的并发量以外,也可以做负载均衡,避免单点故障。

1.2 提升系统的容错能力

一个线程可以不受其他线程的干扰独立运行,如果此线程出现异常退出,其他线程可以不受干扰的继续执行,不至于整个系统崩溃。

2. CPU高速缓存

通过并发我们可以更加充分的利用CPU,CPU的计算通常需要与内存交互,如读取运算数据,存储运算结果,但是这种I/O操作的速度远远比CPU计算的速度要慢的多。为了解决这种硬件效率的不一致,现在的计算机系统都会增加一层高速缓存(读写速度接近于CPU运算速度)来作为内存和CPU之间的缓冲,CPU在工作时会将运算使用到的数据从主内存复制到高速缓存中,利用高速缓存来进行中间结果的保存读取,CPU在计算结束后再把高速缓存的结果同步回主内存,这样就可避免缓慢的主内存读写。

3. 缓存一致性

高速缓存虽然解决了硬件的速度一致性,但是同样也引入了缓存一致性问题。每个处理器都有自己的高速缓存,而这些处理器又共享同一主内存。当多个处理器任务都涉及同一块主内存区域时,将会导致各自的缓存数据不一致。

为了解决一致性问题,需要各个处理器访问缓存时都遵循一些协议,在读写时要根据协议进行操作,这类协议有MSI、MESI、Synapse以及FireFly等。

4. 什么是内存模型

内存模型可以理解为在特定的操作协议下,对特定内存或高速缓存进行读写访问的过程抽象。不同架构的物理机器拥有不一样的内存模型,而Java虚拟机也有自己的内存模型。

5. Java内存模型

Java虚拟机在工作时也有自己的主内存,每个线程有自己的工作内存,这就好比CPU高速缓存和物理机主内存一样,工作内存也是为了获得更好的执行速率。

Java内存模型主要围绕以下三个特性展开:

  1. 原子性
  2. 可见性
  3. 有序性

5.1 主内存和工作内存交互协议

主内存和工作内存的交互协议规定了一个变量如何从主内存拷贝到工作内存,如何从工作内存同步回主内存。Java内存模型中规定了8种操作来完成以上过程,且虚拟机在实现这8种操作时必须要保证原子性,所谓的原子性指的是操作不可再分。这8种操作如下:

lock:作用于主内存的变量,把一个变量标识为一条线程独占的状态

unlock:作用于主内存的变量,把一个处于锁定状态的变量释放,以便后续被其他线程锁定

read:作用于主内存的变量,它把一个变量的值从主内存传输到线程的工作内存中,以便后续的load使用

load:作用于工作内存的变量,它把read操作从主内存中得到的变量值放入工作内存的变量副本中

use:作用于工作内存的变量,它把工作内存中的一个变量的值传递给执行引擎,每当虚拟机遇到一个需要使用到变量的值的字节码指令时就会执行这个操作

assign:作用于工作内存的变量,它把一个从执行引擎接收到的值赋值给工作内存中的变量,每当虚拟机遇到一个给变量赋值的字节码指令时就执行这个操作

store:作用于工作内存的变量,它把工作内存中一个变量的值传送到主内存中,以便后续的write操作使用

write:作用于主内存的变量,它把store操作从工作内存中得到的变量的值写入主内存的变量中

上述指令有以下规定:

  1. read和load、store和write两对操作必须成对存在,且上述两对操作中每一组操作必须顺序执行,但可以不连续,例如:
代码语言:javascript
复制
read a -> read b -> load b -> load a 
  1. 不允许一个线程丢弃他最近的assign动作,也就是变量值在工作内存中修改了以后必须同步回主内存
  2. 不允许一个线程无原因(没有assign动作)的把数据从工作内存中同步回主内存
  3. 一个变量只能在主内存中诞生,不允许在工作内存中使用一个未初始化的变量(变量没有执行过load和assign操作)
  4. 一个变量可以在同一个线程中多次执行lock操作,但必须执行相同次数的unlock操作变量才可以解锁
  5. 如果对一个变量执行lock操作,那将会清空工作内存中此变量的值,在执行引擎使用这个变量前,需要重新执行load或assign操作初始化变量的值
  6. 一个变量没有执行过lock操作,则不允许对其执行unlock操作
  7. 对一个变量执行unlock操作之前,必须先把此变量同步回主内存(store和write)
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-03-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员修炼笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
负载均衡
负载均衡(Cloud Load Balancer,CLB)提供安全快捷的流量分发服务,访问流量经由 CLB 可以自动分配到云中的多台后端服务器上,扩展系统的服务能力并消除单点故障。负载均衡支持亿级连接和千万级并发,可轻松应对大流量访问,满足业务需求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档