volatile与synchronized关键字笔记

一.结论

synchronized:保证了程序执行的可见性和原子性
volatile:保证了可见性和有序性,不保证原子性

二.性质

1. 概念

原子性:和数据库事务中的原子性一样,满足原子性特性的操作是不可中断的,要么全部执行成功要么全部执行失败

有序性:编译器和处理器为了优化程序性能而对指令序列进行重排序,也就是你编写的代码顺序和最终执行的指令顺序是不一致的,重排序可能会导致多线程程序出现内存可见性问题

可见性:多个线程访问同一个共享变量时,其中一个线程对这个共享变量值的修改,其他线程能够立刻获得修改以后的值

2. 概念解析

2.1原子性

最小的操作单元,就是一个原子性操作,例如 i = 1;

多个处理器同时对共享变量进行读改写操作(i++就是经典的读改写操作),那么

共享变量就会被多个处理器同时进行操作(详细看原子操作原理)

,这样读改写操作就不是原子的,操作完之后共享变量的值会和期望的不一致。

2.2有序性

instance = new Instance();创建了一个新对象,这一 行代码可以分解为如下的3行伪代码。

memory = allocate(); // 1:分配对象的内存空间
ctorInstance(memory); // 2:初始化对象
instance = memory; // 3:设置instance指向刚分配的内存地址

我们知道,编辑器和处理器会进行代码优化,而其中重要的一点是会将指令进行重排序。 上边的代码经过重排序后可能会变为

memory = allocate(); // 1:分配对象的内存空间
instance = memory; // 3:设置instance指向刚分配的内存地址(此时对象尚未初始化)
ctorInstance(memory); // 2:初始化对象

这样会引起一些问题,打个比方,有一个线程A在创建对象,另一个线程B判断对象是否为空if (instance == null),如果指令被重排序,那么当A尚未初始化对象但已分配内存地址时,若B在做判断,会得到错误的结果。 所以,用 volatile来禁止上述指令的重排序,使B的判断不会出错。

2.3可见性

多个线程将同一个数据读取到各自的缓存区后,某个cpu修改了缓存的数据之后,会立马同步给主存,volatile就是这么实现可见性的

多个线程将同一个数据读取到各自的缓存区后,某个cpu修改了缓存的数据之后,会立马同步给主存,volatile就是这么实现可见性的

参考链接

原子操作的实现原理
volatile 禁止指令重排序
volatile是如何是实现可见性的

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值