一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第9天,点击查看活动详情。
硬件上的内存模型
计算机在执行程序的时候,指令都是在CPU中执行的,执行指令的过程需要涉及到读写数据,CPU的读写是很快的,内存的读写没有CPU读写快,如果让cpu和内存直接交互的话内存就是性能的瓶颈,于是乎就引入了一个缓存内存的概念。
如果是单条指令执行这个模型是没有问题的,如果是多个一起执行的话,就会导致一些问题(原本改引用的结果变成了初始的值),这个时候就引入了缓存一致性协议
JMM
Java Memory Model(java内存模型),也是一种规范,是个抽象模型
- 定义了JVM在计算机内存(RAM)中的工作方式
- 定义了主内存与线程工作内存之间的关系,类似于硬件层面上,内存和CPU的关系
- 线程工作内存并不是物理存在的,实现方式包括硬件的高速缓存,寄存器或是编译机优化。
JMM8大原子操作
- lock:标识一个变量为线程独占
- unlock:释放一个变量的线程独占状态
- read:把变量值从主内存传输到工作内存
- load:把read的值给变量副本
- use:执行引擎使用变量的值
- assign:将执行引擎收到的值放入变量副本
- store:把变量值从工作内存传输到主内存
- write:把store的值给变量
并发编程三大要素
- 原子性:一个或一组操作是不可分隔的原子,不能打断
- 可以通过synchronized和一些lock来保证
- 可见行:一个线程修改变量后,立即能被另一个线程观测到
- volatile关键字要求变量被修改后立即同步到主内存,每次使用时也必须从主内存读取
- synchronized保证,在加锁前清空工作内存的变量值,从主内存重新读取,在释放锁前把工作内存变量刷新回主内存
- 有序性:程序的执行顺序,对线程外部来说,是固定且可预期的
- synchronized能够保证代码层面,对线程外部的有序性
- volatile则能够防止指令重排序
指令重排序
在执行指令时,出于提高性能等原因,编译器,处理器会改变指令的执行顺序
- 重排序不能改变程序在单线程下的执行结果(as-if-serial原则)
- 不会对存在依赖关系的指令进行重排序(happens-before原则)