JAVA内存模型 读书笔记

学习内容链接https://www.cnblogs.com/yanlong300/p/9009687.html

 

 

JAVA内存模型定义

CPU有缓存一致性协议及内存屏障。而JAVA是一个跨平台的语言,为了实现一处编码处处执行的功能。JAVA需要设计一个中间层模型来匹配不同操作系统及硬件上的差异。

java内存模型(java memory model): java内存模型指定的是java虚拟内存如何与计算机内存(硬件实体RAM)一起配合。java虚拟机本身就是一个抽象的计算机模型,所以java内存模型更贴切的说是虚拟机内存的使用规范。

 

JAVA内存模型的介绍

java内存模型主要有以下结构:

  1. stack(栈)
    特点: 存取速度快、对象生命周期确定、数据大小确定。
    存储数据:基本类型变量、对象引用(句柄)
    位置:缓存、寄存器、写缓冲区。

  2. heap(堆)
    特点: 存取速度慢、运行时动态分配大小、对象生命抽周期不确定、垃圾回收。
    存储数据:对象
    位置:主内存、缓存

 

理论上stack和heap都存储在计算机的主内存上,但是随着CPU的计算其副本会被加载到缓存及寄存器持有,持有的数据遵从MESI缓存一致性原则。

 

JAVA内存模型的结构

JMM对共享内存的操作做出了两条规则:

1.线程对共享内存的中的变量的操作都必须在自己的工作内存中进行,不能直接在主内存中进行读写。

2.不同线程无法直接访问其他线程工作内存中的变量,因此共享变量的值传递需要通过主内存完成。

JAVA并发问题的根源

假设线程A和线程B同事访问某个对象的成员变量x。当线程a需要操作变量a,时会将a副本复制到线程A的工作内存中。

当线程a未执行完毕,线程b也要访问变量a

但是线程a与线程b操作的是自己工作空间中的变量副本。 线程a中的副本和线程b中间的副本相符不可见。如果a线程率先完成了任务并写回主存。那么线程b的运算就是在使用后脏数据运算。如果b也写回主存那么线程a的任务就会丢失。

为了保证程序的准确性,我们就需要在并发时添加额外的同步操作。

JAVA并发问题的解决方案

操作过程

我们接着再来关注下变量从主内存读取到工作内存,然后同步回工作内存的细节,这就是主内存与工作内存之间的交互协议。Java内存模型定义了以下8种操作来完成,它们都是原子操作(除了对long和double类型的变量)。

锁定(lock):作用于主内存中的变量,将他标记为一个线程独享变量。

通常意义上的上锁,就是一个线程正在使用时,其他线程必须等待该线程任务完成才能继续执行自己的任务。

解锁(unlock):作用于主内存中的变量,解除变量的锁定状态,被解除锁定状态的变量才能被其他线程锁定。

执行完成后解开锁。

read(读取):作用于主内存的变量,它把一个变量的值从主内存传输到线程的工作内存中,以便随后的load动作使用。

从主内存 读取到工作内存中。

load(载入):把read操作从主内存中得到的变量值放入工作内存的变量的副本中。

给工作内存中的副本赋值。

use(使用):把工作内存中的一个变量的值传给执行引擎,每当虚拟机遇到一个使用到变量的指令时都会使用该指令。

程序执行过程中读取该值时调用。

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

将运算完成后的新值赋回给工作内存中的变量,相当于修改工作内存中的变量。

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

将该值从变量中取出,写入工作内存中。

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

将工作内存中的值写回主内存。

解决方案

很简单~加锁。同一时间一个变量只允许一个线程持有一个变量,其他线程需要等待线程使用完后在主内存中解锁才能持有使用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值