java cas 实现_Java CAS算法简介及简单模拟CAS算法
CAS(Compare-And-Swap:比较并替换)
CAS是英文单词CompareAndSwap的缩写,意思就是:比较并替换。简单来说就是比较之后再看情况是否需要替换。CAS是乐观锁思想的一种实现方式。
一、CAS运算流程
CAS算法的流程是:先读取一个预期值(A) → 从内存中读取一个值(V),如果A == V,那么就将新的值(B)给写入内存,如果A != V,那就不做任何操作。
二、CAS的优缺点
优点:①可以避免优先级倒置和死锁。②允许更高程度的并行机制
缺点:①ABA问题:(可能会造成数据丢失)
比如有三个线程ThreadA、ThreadB、ThreadC,这三个线程都要操作一个值value(value初始值为100)。
三个线程的目的:
ThreadA(value = 100 → value = 50);
ThreadB(value = 100 → value = 50);
ThreadC(value = 50 → value = 100);
刚开始线程A和B都开始运行,两个线程读取到的预期值都是100,此时线程A将100给改为50,之后C线程突然出现,将50给改成了100,然后线程B被插队了就很不爽,准备去修改值,但是读取到了内存值是100 == 预期值100,于是就把100给修改成了50。可是线程B很纳闷,前两个线程到底搞什么飞机,咋啥也没干,他们是没操作成功还是根本没修改这个值?这内存中的值还是100,我还以为我会修改失败呢。
所以,线程B纳闷的点就是CAS的缺点,它只能去判断内存值和预期值是否相等来得出这个数是否被别人修改过,但是却不知道,读取了预期值100之后,中间被插了无数队,轮到我去修改时,发现内存值等于预期值就以为前面的线程都没有修改这个数,然后线程B就把值给修改了。然而线程B修改值却一直以为他操作的数是被插队之前的那个数,所以线程B的修改会忽略掉中间插队那些线程的操作,所以线程B的修改可能会造成数据丢失。
解决办法:Java提供了一个带有标记的原子类AtomicStampedReference,它可以通过控制变量值的版本来保证CAS的正确性
②CAS只能保证一个共享变量的原子性操作。
解决办法:可以把多个变量放进一个对象里来进行CAS操作
③循环时间长,CPU的开销大。
三、模拟CAS算法(只是模拟,并非Java底层的真正实现)
/**
* @author 弹弹霹雳
* @create 2020-11-22-11:43
*/
//模拟CAS算法
public class TestCompareAndSwap {
public static void main(String[] args) {
CompareAndSwap cas = new CompareAndSwap();
//创建10个线程
for(int i = 0 ; i < 10; i++){
new Thread(new Runnable() {
@Override
public void run() {
//获取预期值
int expectedValue = cas.getValue();
//尝试去修改值,并接收修改情况
boolean flag = cas.compareAndSet(expectedValue, (int)(Math.random() * 101));
System.out.println(flag);
}
}).start();
}
}
}
class CompareAndSwap{
//通过volatile保证内存的可见性
private volatile int value = 0;
public int getValue(){
return this.value;
}
public synchronized int compareAndSwap(int expectedValue, int newValue){
//读取内存中的值
int oldValue = this.value;
//如果内存中的值和预期值相等,那么我们就修改内存中的值
if(expectedValue == oldValue){
this.value = newValue;
}
//返回内存值,如果value被修改,返回的是修改前的值,主要用来给compareAndSet判断是否修改成功
return oldValue;
}
public boolean compareAndSet(int expectedValue, int newValue){
//如果预期值和内存值相等,就返回true否则返回false
return expectedValue == compareAndSwap(expectedValue, newValue);
}
}
本文分享 CSDN - 弹弹霹雳。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。
java cas 实现_Java CAS算法简介及简单模拟CAS算法相关推荐
- java+mock+例子_java – 如何使用PowerMock和Mockito模拟枚举类的实例?
我试着按照这个非常相似的问题的答案提供的例子,但它对我不起作用.我收到以下错误消息: java.lang.IllegalArgumentException: Cannot subclass final ...
- java老年代_Java新生代老年代的划分及回收算法
Java堆(Java Heap)是JVM所管理的最大内存区域,也是所有线程共享的一块区域,在JVM启动时创建. 此内存区域存放的都是对象的实例和数组.JVM规范中说到:"所有的对象实例以及数 ...
- java范形_java范型简介
java范型简介 一.简单认识java范型 经常听人说"范型",我一直不是太明白什么叫"范型",今天就查阅了一些文章,给我的第一感觉就是之所以在java中用范型 ...
- C语言、Java学习笔记(三)---几种简单的排序算法
假期已经过了一半,整个人都变得颓废了许多.今天没有出去玩,就学了几个简单的排序算法,以求安慰自己,好歹也是在假期里学习过了.(瘫- C 这里一次性给出三种排序方法的代码,分别是冒泡排序,选择排序和归并 ...
- Jmeter简介以及简单模拟性能测试
1.Jemter简介 1.我们为什么使用Jmeter 开源,免费,基于Java编写,可集成到其他系统可拓展各个功能插件 支持接口测试, 压力(负载和压力)测试等多种功能,支持录制回放, 入门简单相较于 ...
- 简单模拟Lur 算法
import java.util.LinkedHashMap; import java.util.Map;//模拟Lur 算法 public class redisLUR<K,V> ext ...
- 算法其实很简单—弗洛伊德(Floyd)算法
目录 1.弗洛伊德(Floyd)算法介绍 2.弗洛伊德(Floyd)算法最佳应用-最短路径 3.弗洛伊德(Floyd)算法图解分析 3.1 弗洛伊德算法的步骤: 4.代码实现 1.弗洛伊德(Floyd ...
- 算法其实很简单—克鲁斯卡尔算法
目录 1. 克鲁斯卡尔算法介绍 2. 公交站问题 2.1 克鲁斯卡尔算法图解 2.2 克鲁斯卡尔算法分析 2.3 如何判断是否构成回路 3. 代码实现 1. 克鲁斯卡尔算法介绍 1)克鲁斯卡尔(Kru ...
- python选择排序算法图解_简单选择排序算法(C语言详解版)
该算法的实现思想为:对于具有 n 个记录的无序表遍历 n-1 次,第 i 次从无序表中第 i 个记录开始,找出后序关键字中最小的记录,然后放置在第 i 的位置上. 例如对无序表{56,12,80,91 ...
最新文章
- GDCM:gdcm::GroupDict的测试程序
- CentOS 6.5下利用Rsyslog+LogAnalyzer+MySQL部署日志服务器
- Jinja2学习笔记暨官方文档的翻译 -- 转载
- MySQL增量备份及恢复
- 《软件需求最佳实践》阅读笔记02
- PHP Cookbook读书笔记 – 第13章Web自动化
- r语言转python,R语言与python语言读写loom文件
- CleanMyMac4.12最新版mac系统内存空间清理教程
- Web性能技巧-超越基础
- 【Javascript】二十个工具函数
- C++ vector 容器的全排列算法 next_permutation
- duilib开发(五):界面布局
- 2017多校 Balala Power!
- 【Windows10调教】注册表法一键修改COM口属性,使串口调试显示更直观
- android 摄像头 蓝条,微信小程序拍照部分Android机出现蓝色精灵人现象
- 软件开发的定律:布鲁克定律
- 1、WebApi简介
- Oracle10R2新特性之Transparent Data Encryption
- 计算机多媒体技术及其应用论文,浅析计算机多媒体技术的应用
- 单链表操作——交换节点