java并发:CAS算法和ABA问题
CAS算法是硬件对于并发的支持,针对多处理器操作而设计的处理器中的一种特殊指令。
CAS用于管理对共享数据的并发访问。
java的并发包中,AQS、原子操作类等都是基于CAS实现的。
CAS 是一种 无锁的 非阻塞算法的 实现。
CAS(Compare-And-Swap),简单来说就是比较和替换。
比较和替换是使用一个期望值和一个变量的当前值进行比较,如果当前变量的值与我们期望的值相等,就使用一个新值替换当前变量的值。
比如说,想使用一台机器,先通过比较判断这台机器是否处于未占用状态,如果机器处于未占用状态,就将它设为使用状态。
CAS 包含了三个操作数:
需要读写的内存值: V,进行比较的预估值: A,拟写入的更新值: B。
当且仅当 V == A 时, V = B, 否则,将不做任何操作;
以下用同步锁synchronized模拟CAS 算法。
注意:真正的CAS算法是无锁的。
如下:
public class CasDemo {
public static void main(String[] args) {
final CompareAndSwap cas = new CompareAndSwap();
for(int i=0; i<10; i++){
// 创建10个线程,模拟多线程环境
new Thread(new Runnable(){
@Override
public void run(){
int expectedValue = cas.get();
boolean b = cas.compareAndSwap(expectedValue, (int)(Math.random()*5));
}
}).start();
}
}
static class CompareAndSwap{
private int value;
// 获取内存值
public synchronized int get() {
return value;
}
// 比较当前值和期望值,相同就替换。
public synchronized boolean compareAndSwap(int expectedValue,int newValue) {
//获取旧值
int oldValue=value;
if(oldValue==expectedValue) {
this.value=newValue;
System.out.println(Thread.currentThread().getName()+"比较当前值和期望值,结果一致,将其替换为新值。");
return true;
}
System.out.println(Thread.currentThread().getName()+"比较当前值和期望值,结果不一致,不替换为新值");
return false;
}
}
}
ABA问题:
尽管CAS看起来没问题,其实存在一个逻辑漏洞。
如果一个变量V初次读取时是A值,并且在赋值时检查到它仍然是A值,那么我们就能说它的值没有改变过吗?
如果在此期间,它的值曾经改成了B,后来又改回为A。那么CAS操作就会误以为它从来没有改变过。
这个称为CAS的“ABA”问题。
当然,在大部分情况下ABA问题并不会影响程序并发的正确性。如果需要解决ABA问题,可以改用传统的互斥同步。
java并发:CAS算法和ABA问题的更多相关文章
- Java多线程_CAS算法和ABA问题
CAS算法概述CAS是英文单词CompareAndSwap的缩写,中文意思是:比较并替换.CAS需要有3个操作数:内存地址V,旧的预期值A,即将要更新的目标值B. CAS指令执行时,当且仅当内存地址V ...
- Java并发——CAS
什么是CAS? CAS是Compare And Swap的简称.在Java中有很多实现,比如compareAndSwapObject()方法,或者compareAndSwapInt()方法等.多用在包 ...
- java并发编程(十三)----(JUC原子类)引用类型介绍(CAS和ABA的介绍)
这一节我们将探讨引用类型原子类:AtomicReference, AtomicStampedRerence, AtomicMarkableReference.AtomicReference的使用非常简 ...
- Java并发编程入门与高并发面试(三):线程安全性-原子性-CAS(CAS的ABA问题)
摘要:本文介绍线程的安全性,原子性,java.lang.Number包下的类与CAS操作,synchronized锁,和原子性操作各方法间的对比. 线程安全性 线程安全? 线程安全性? 原子性 Ato ...
- Java并发问题--乐观锁与悲观锁以及乐观锁的一种实现方式-CAS
首先介绍一些乐观锁与悲观锁: 悲观锁:总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁.传统的关系型数据库里边就用到了很 ...
- Java并发编程:什么是CAS?这回总算知道了
无锁的思想 众所周知,Java中对并发控制的最常见方法就是锁,锁能保证同一时刻只能有一个线程访问临界区的资源,从而实现线程安全.然而,锁虽然有效,但采用的是一种悲观的策略.它假设每一次对临界区资源的访 ...
- Java并发(十二):CAS Unsafe Atomic
一.Unsafe Java无法直接访问底层操作系统,而是通过本地(native)方法来访问.不过尽管如此,JVM还是开了一个后门,JDK中有一个类Unsafe,它提供了硬件级别的原子操作. 这个类尽管 ...
- Java 并发(一) --- CAS
CAS 原理 先来看看下面的代码是否可以输出预期的值.开启了两个线程,是否会输出200 呢 结果由于并发的原因,结果会小于或等于200 , 原因出现在 count++; 由于这一行代码存在三个操作: ...
- Java并发编程系列-(3) 原子操作与CAS
3. 原子操作与CAS 3.1 原子操作 所谓原子操作是指不会被线程调度机制打断的操作:这种操作一旦开始,就一直运行到结束,中间不会有任何context switch,也就是切换到另一个线程. 为了实 ...
随机推荐
- 【Spring学习笔记-3.1】让bean获取spring容器上下文(applicationContext.xml)
*.hl_mark_KMSmartTagPinkImg{background-color:#ffaaff;}*.hl_mark_KMSmartTagBlueImg{background-color:# ...
- Mybatis学习(4)输入映射、输出映射、动态sql
一.输入映射: 通过parameterType指定输入参数的类型,类型可以是简单类型.hashmap.pojo的包装类型 1) 传递pojo的包装对象 需求是:完成用户信息的综合查询,传入的查询条件复 ...
- 导入testng管理测试用例
1.在pom.xml中增加testng的依赖,以导入testNG 2.在src-main-resources目录下新建xml文件,比如untitled.xml. <?xml version=&q ...
- 快速开发jQuery插件的10大技巧
原文链接:http://wiki.itivy.com/?p=36 在开发过很多 jQuery 插件以后,我慢慢的摸索出了一套开发jQuery插件比较标准的结构和模式.这样我就可以 copy & ...
- pyplot 绘图与可视化
1. 基本使用 #!/usr/bin/env python # coding=utf-8 import matplotlib.pyplot as plt from numpy.random impor ...
- Eclipse修改workspace目录的几种方式
Eclipse是一款很强的Java IDE,我们在开始的时候,往往设定了默认的workspace,当用久在之后,我们可能要去更改一下workspace的位置.下面有几种方法可以更改workspace的 ...
- pandas的map函数与apply函数的区别
import pandas as pd import numpy as np df = pd.DataFrame(np.random.randn(4,3),columns=list("ABC ...
- linux&android PPP 相关知识
Linux&Android PPP相关FAQ 目录 Linux&Android PPP相关FAQ.. 1 一. 文档说明... 3 二. 常见调试技 ...
- Spring MVC 原生API
原生API: Servlet环境中一些有用的对象: HttpServletRequest HttpServletResponse HttpSession Reader Writer InputStre ...
- spring boot 整合 (全)
参考: https://github.com/spring-projects/spring-boot/tree/master/spring-boot-samples