cas原理和volatile
文章目录
- volatile为什么不能保证原子性?
- cas 原理?
- cas原子性原理
- cas如何保证可见性?
- cas缺点
- CAS包含哪些参数:
- 循环CAS:
- double check 单例模式中,变量为什么定义成volatile?
volatile为什么不能保证原子性?
1.首先volatile可以保证变量每次读的都是最新值。但是在并发操作中,向i++,这种操作不是原子性,因为这里涉及到了多个操作,1.线程A 获取i的值100,这个时候获取的是最新值,此时由于线程阻塞等原因,线程B获取的最新值100,然后将i 自增到101,更新到内存。
此时线程A又来进行一次自增操作,又将101更新到内存。两个自增结果都是101,跟我们预期不一致,所以并不是原子操作。但是,每次获取值都是最新的,volatile保证了可见了,保证每次值的更新都更新到了主存,每次获取到的都是最新值
cas 原理?
cas原子性原理
将预期值和内存的值进行比较,如果两者相等就进行更新操作,更新操作是通过unsafe调用的操作系统底层的方法,大概是cpu会将缓存的值进行加一个总线锁,保证数据操作的原子性。
cas如何保证可见性?
我们通过cas处理的变量,可以设置为volatile,cpu底层会采用内存屏障保证数据可见性,cpu中有个高速缓存,每次更新值,会直接更新到主内存,刷新高速缓存。读取值的时候,会直接从主存读取数据
cas缺点
缺点有三。
1.cas是一种类似乐观锁的时间,如果资源的竞争比较激烈。那么每次都到内存做cas判断,会想好资源。这时候可能还没有悲观锁的好。
2.cas可能存在ABA的问题,第一:线程 1 和线程2都读取值 A,但是线程1执行很快,将值更新为B,一番操作后,线程2又更新为A,这时候线程1进行cas操作,发现内存中是A,然后继续操作。所以也是执行成功,但是整个过程有问题,因为数据做了变更,但是线程1却不知道。
解决办法: java中提供了一个AtomicStampedReference来处理ABA问题,相当于在对象中额外增加一个标记来标记对象是否有过变更。
3.cas只能保证单个标量的原子性,却不能同时保证多个变量的原子性,可以将把多个共享变量合并成一个共享变量来操作。比如有两个共享变量i=2,j=a,合并一下ij=2a,然后用CAS来操作ij
在java的并发包中,通常用cas配合变量的volatile,保证数据操作的原子性可见性。
CAS包含哪些参数:
unsafe.compareAndSwapObject(this, headOffset, null, update)
三个运算符:
个是this,也就是unsafe这个对象
一个内存地址V
一个期望的值A
一个新值B
基本思路:
如果地址V上的值和期望的值A相等,就给地址V赋值新值B,如果不是,不做任何操作
循环CAS:
在一个(死)循环中里不断进行CAS操作,直到成功为止(自旋操作即死循环)
每次操作都取出最新值跟内存中的比较,cas比较失败,就从新拿最新值进行比较。比如在可重入锁的节点加入队列时候,用到自旋的cas。缺点是竞争比较高时候,无效的自旋操作浪费性能。
private Node enq(final Node node) {for (;;) {Node t = tail;if (t == null) { // Must initializeif (compareAndSetHead(new Node()))tail = head;} else {node.prev = t;if (compareAndSetTail(t, node)) {t.next = node;return t;}}}}
double check 单例模式中,变量为什么定义成volatile?
比如定义一个person: Person p = new Person().
这里大概涉及到三个操作。
第一:new person 在内存开辟空间。
第二:调用person构造方法
第三:将new person的引用复制给变量p.
由于jvm的内部优化,执行过程可能会指令重排。 也就是说,将变量的赋值操作和对象的构造方法操作,可能会重排序,那么double check在并发的时候,可能拿到的一个空的对象,也就是没有属性值的对象。
所以可以使用volatile,禁止指令重排序,相当于是加了一个内存屏障,数据每次读都是从主存中读,写会更新到主存,刷新缓存。
但是volatile不能保证原子,类似变量的自增操作这种,不是一个原子操作。只能保证每次读的都是最新数据,不会说存在线程A更新了,线程B却读的老的。
cas原理和volatile相关推荐
- Mybatis插件原理和PageHelper结合实战分页插件(七)
今天和大家分享下mybatis的一个分页插件PageHelper,在讲解PageHelper之前我们需要先了解下mybatis的插件原理.PageHelper 的官方网站:https://github ...
- HBase学习指南之HBase原理和Shell使用
HBase学习指南之HBase原理和Shell使用 参考资料: 1.https://www.cnblogs.com/nexiyi/p/hbase_shell.html,hbase shell 转载于: ...
- IAP的原理和stm8的IAP
一.引出(IAP的原理和stm8上实现IAP的问题) 具有IAP功能的单片机,程序可以分为两部分:IAP和APP.APP是用来实现真正功能的程序,而IAP是用来远程重新编程APP的程序.单片机上电时会 ...
- 单链表反转的原理和python代码实现
链表是一种基础的数据结构,也是算法学习的重中之重.其中单链表反转是一个经常会被考察到的知识点. 单链表反转是将一个给定顺序的单链表通过算法转为逆序排列,尽管听起来很简单,但要通过算法实现也并不是非常容 ...
- 计算机网络原理和OSI模型与TCP模型
计算机网络原理和OSI模型与TCP模型 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.计算机网络的概述 1.计算机网络的定义 计算机网络是一组自治计算机的互连的集合 2.计算机 ...
- HTTPS原理和CA证书申请
转载自:HTTPS原理和CA证书申请(满满的干货) 众所周知,WEB服务存在http和https两种通信方式,http默认采用80作为通讯端口,对于传输采用不加密的方式,https默认采用443,对于 ...
- class加载原理和Dex加载的原理-----android插件化技术
2019独角兽企业重金招聘Python工程师标准>>> class加载原理和Dex加载的原理 转载于:https://my.oschina.net/quguangle/blog/15 ...
- 转载椭圆曲线原理和openssl命令操作
原文地址:https://www.johannes-bauer.com/compsci/ecc/ 椭圆曲线原理和openssl命令操作
- mvc原理和mvc模式的优缺点
mvc原理和mvc模式的优缺点 一.mvc原理 mvc是一种程序开发设计模式,它实现了显示模块与功能模块的分离.提高了程序的可维护性.可移植性.可扩展性与可重用性,降低了程序的开发难度.它主要分 ...
最新文章
- java 获取系统当前时间
- 【Leetcode】两个有序数组,求第k大的数
- 横向扩展你的ASP.NET Core SignalR 应用
- UE3 关卡优化指南
- 解决Vscode提示bodyparser已被弃用的问题
- GreenDao 工具类 --- 使用 Json 快速生成 Bean、表及其结构,炒鸡快!
- Python - 优雅而简单地完成http请求
- c语言如何输入未知数据类型的_C语言新手踩坑记!大坑小坑全部都是你的!
- python 框架是什么意思_Python框架有哪些?区别是什么?
- java非法表达式开头,java - 我不断收到“ Battle.java:11:错误:表达式的非法开头” Heelp - SO中文参考 - www.soinside.com...
- SpringCloud之Ribbon源码分析(一)
- 难道真的是RPWT-LFS日记1
- Could not import the lzma module
- 计算机科学美国大学专业,最新!2019年USNews美国大学计算机专业排名
- Flixel横板游戏制作教程(二)— AddingPlayer
- 六爻金钱卦 手工摇卦方法
- Android Scroll实现弹性滑动 一 列表下拉弹性滑动
- 【写作】论文写作技巧
- 嵌入式平台ssh开发环境搭建
- 某公司HP-EVA4400存储硬盘离线的数据恢复方法和数据恢复过程