【JUC系列第三篇】-CAS算法详解
作者 : 毕来生
微信: 878799579
1、CAS是什么?
CAS是英文单词(Compare-And-Swap)的缩写,中文意思是:比较并替换。CAS需要有3个操作数:内存地址V,旧的预期值A,即将要更新的目标值B。
CAS指令执行时,当且仅当内存地址V的值与预期值A相等时,将内存地址V的值修改为B,否则就什么都不做。整个比较并替换的操作是一个原子操作。
Cas乐观锁算法演示
CAS优缺点
优点:
- 解决了部分情况下原子操作的问题
- 并发量不是很高时cas机制会提高效率。
缺点:
同一时间只能保证一个共享变量的原子操作(针对多个共享变量操作。循环CAS无法保证操作原子性,需要考虑通过加锁来保证原子性)
循环时间比较长,且开销时间比较大 : 如果尝试CAS失败,则会一直进行尝试。如果一直不成功。会对CPU带来较大负担
经典ABA问题
如果内存地址V初次读取的值是A,并且在准备赋值的时候检查到它的值仍然为A,那我们就能说它的值没有被其他线程改变过了吗?
如果在这段期间它的值曾经被改成了B,后来又被改回为A,那CAS操作就会误认为它从来没有被改变过。这个漏洞称为CAS操作的“ABA”问题。Java并发包为了解决这个问题,提供了一个带有标记的原子引用类“AtomicStampedReference”,它可以通过控制变量值的版本来保证CAS的正确性。因此,在使用CAS前要考虑清楚“ABA”问题是否会影响程序并发的正确性,如果需要解决ABA问题,改用传统的互斥同步可能会比原子类更高效。
如何解决经典ABA问题以及源码分析
通过JDK中自带的AtomicStampedReference类可以解决ABA问题。附上核心解决方法
/**
* Atomically sets the value of both the reference and stamp
* to the given update values if the
* current reference is {@code ==} to the expected reference
* and the current stamp is equal to the expected stamp.
*
* @param expectedReference the expected value of the reference(期望值)
* @param newReference the new value for the reference(写入新值)
* @param expectedStamp the expected value of the stamp(期望的状态值)
* @param newStamp the new value for the stamp(新的状态值)
* @return {@code true} if successful
*/
public boolean compareAndSet(V expectedReference,
V newReference,
int expectedStamp,
int newStamp) {
Pair<V> current = pair;
return
expectedReference == current.reference &&
expectedStamp == current.stamp &&
((newReference == current.reference &&
newStamp == current.stamp) ||
casPair(current, Pair.of(newReference, newStamp)));
}
private boolean casPair(Pair<V> cmp, Pair<V> val) {
return UNSAFE.compareAndSwapObject(this, pairOffset, cmp, val);
}
因为casPair核心方法时通过native关键字修饰。故不能直接查看对应class源码。
public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5)
不能查看源码就能难住我们了?不存在的。
我们下载好openjdk源码后,将其导入到idea里该project的lib中,全局搜索。直接附上对应源码供大家参考
UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject e_h, jobject x_h))
UnsafeWrapper("Unsafe_CompareAndSwapObject");
oop x = JNIHandles::resolve(x_h); // 新值
oop e = JNIHandles::resolve(e_h); // 预期值
oop p = JNIHandles::resolve(obj);
HeapWord* addr = (HeapWord *)index_oop_from_field_offset_long(p, offset);// 在内存中的具体位置
oop res = oopDesc::atomic_compare_exchange_oop(x, addr, e, true);// 调用了另一个方法
jboolean success = (res == e); // 如果返回的res等于e,则判定满足compare条件(说明res应该为内存中的当前值),但实际上会有ABA的问题
if (success) // success为true时,说明此时已经交换成功(调用的是最底层的cmpxchg指令)
update_barrier_set((void*)addr, x); // 每次Reference类型数据写操作时,都会产生一个Write Barrier暂时中断操作,配合垃圾收集器
return success;
UNSAFE_END
【JUC系列第三篇】-CAS算法详解的更多相关文章
- OSGi 系列(三)之 bundle 详解
OSGi 系列(三)之 bundle 详解 1. 什么是 bundle bundle 是以 jar 包形式存在的一个模块化物理单元,里面包含了代码,资源文件和元数据(metadata),并且 jar ...
- 安全体系(三)——SHA1算法详解
本文主要讲述使用SHA1算法计算信息摘要的过程. 安全体系(零)—— 加解密算法.消息摘要.消息认证技术.数字签名与公钥证书 安全体系(一)—— DES算法详解 安全体系(二)——RSA算法详解 为保 ...
- Spring之旅第三篇-Spring配置详解
上一篇学习了IOC的概念并初步分析了实现原理,这篇主要学习Spring的配置,话不多说,让我们开始! 一.Bean元素配置 1.1 基本配置 看一个最基本的bean配置 <bean name=& ...
- G1混合式GC与三色标记算法详解【纯理论】
继续基于上一次https://www.cnblogs.com/webor2006/p/11146273.html的理论进一步了解G1. G1收集概览: G1算法将堆划分为若干个区域(Region),它 ...
- Kafka 系列(三)—— Kafka 生产者详解
一.生产者发送消息的过程 首先介绍一下 Kafka 生产者发送消息的过程: Kafka 会将发送消息包装为 ProducerRecord 对象, ProducerRecord 对象包含了目标主题和要发 ...
- SpringBoot第三篇:配置文件详解二
作者:追梦1819 原文:https://www.cnblogs.com/yanfei1819/p/10615605.html 版权声明:本文为博主原创文章,转载请附上博文链接! 前言 本文主要讲 ...
- Elasticsearch第三篇:查询详解
从第一篇开始,我用的ES版本就是7.8.0的,与低版本略有不同,不同点可以参考官方介绍,最大的不同就是抛弃 type 这一概念,为了方便测试,首先建立一个学生成绩的索引库(在建立的同时,规定字段类型, ...
- 安全体系(一)—— DES算法详解
本文主要介绍了DES算法的步骤,包括IP置换.密钥置换.E扩展置换.S盒代替.P盒置换和末置换. 安全体系(零)—— 加解密算法.消息摘要.消息认证技术.数字签名与公钥证书 安全体系(二)——RSA算 ...
- Java并发编程之CAS第三篇-CAS的缺点及解决办法
Java并发编程之CAS第三篇-CAS的缺点 通过前两篇的文章介绍,我们知道了CAS是什么以及查看源码了解CAS原理.那么在多线程并发环境中,的缺点是什么呢?这篇文章我们就来讨论讨论 本篇是<凯 ...
随机推荐
- Linux系统目录的学习
1.在公司中linux 都是没有界面 2.系统路径 2.1 /表示根目录 2.2 ~表示/root 2.3etc:存放系统配置文件 2.4 home 除了root 以外所有用 ...
- Beginning Linux Programming 学习-chapter2-Shell programming-Pipes and Redirection
"为了从事创造性工作,人类需要孤独,可是在孤独中,广义的人类仍存在于内心."--(德国)奥铿 ...
- 阿里云RocketMQ的消费者简单实现
业务场景之类的请看另一篇生产者的实现: package com.ttt.eee; import com.aliyun.openservices.ons.api.Action; import com.a ...
- Nachos java版学习(一)
最近,操作系统课程设计使用伯克利大学的Nachos做为实验平台,老师也照搬伯克利的Project要求,开始我们的操作系统课程设计. 结合自己的学习过程和课设要求,我觉得对Nachos的学习首先应该从K ...
- [转帖]新一代IBM Z14主机技术介绍
新一代IBM Z14主机技术介绍 https://cloud.tencent.com/developer/news/268909 IBM最新的已经有IBM Z15 主机了.. 文章来源:企鹅号 - 云 ...
- python之 -> 的含义
函数或方法标注通常用于 :类型提示:例如以下函数预期接受两个 int 参数并预期返回一个 int 值: def sum(a: int, b: int) -> int: return a + b ...
- 开源定时任务框架Quartz(一)
简介 Quartz是OpenSymphony开源组织的一个开源项目,定时任务框架,纯Java语言实现,最新版本为2.3.0. 设计模式 Quartz中使用的设计模式如下: 1.Builder模式 2. ...
- python对影评进行评论分析,形成词云图
1 # -*- coding:utf-8 -*- 2 ''' 3 抓取豆瓣电影某部电影的评论 4抓取电影 5 网址链接:https://movie.douban.com/subject/ ...
- C# explicit interface implementation(显式接口实现)
C# explicit interface implementation 某个类要实现两个包含相同方法名的接口, 应该如何实现这两个方法? namespace ExplicitInterfaceImp ...
- Abp 领域事件简单实践 <三> 自定义事件
熵片用到的 EntityCreatedEventData<TEntity>,继承自EventData. 我们可以自定义事件: public class TestEvent: EventD ...
