Java并发的CAS原理与ABA问题的讲解

作者:JimmyU1 时间:2023-11-25 12:17:21 

CAS原理

在计算机科学中,比较和交换(Compare And Swap)是用于实现多线程同步的原子指令。 它将内存位置的内容与给定值进行比较,只有在相同的情况下,将该内存位置的内容修改为新的给定值。 这是作为单个原子操作完成的。 原子性保证新值基于最新信息计算; 如果该值在同一时间被另一个线程更新,则写入将失败。 操作结果必须说明是否进行替换; 这可以通过一个简单的布尔响应(这个变体通常称为比较和设置),或通过返回从内存位置读取的值来完成(摘自维基本科)

CAS流程

Java并发的CAS原理与ABA问题的讲解

以AtomicInteger.addAndGet()为例讲解CAS

javadoc

public final int addAndGet(int delta)
Atomically adds the given value to the current value, with memory effects as specified by VarHandle.getAndAdd(java.lang.Object…).
Parameters:
delta - the value to add
Returns:
the updated value

在Java的源码中


public final int addAndGet(int delta) {
 return U.getAndAddInt(this, VALUE, delta) + delta;
}

这里的VALUE是在该类初始化的时候获取到的,理解一下就是这时候我们调用unsafe的objectFieldOffset从Atomic类文件中获取value的偏移量,那么VALUE其实就是记录value的偏移量的。

VALUE准确的是value这个字段相对与AtomicInteger这个对象内存起始地址的偏移量,由于这个方法的最底层是JNI调用native的方法,所以需要传入这个值。


private static final long VALUE = U.objectFieldOffset(AtomicInteger.class, "value");

继续往下执行:


/**
* Atomically adds the given value to the current value of a field
* or array element within the given object {@code o}
* at the given {@code offset}.
* @param o object/array to update the field/element in
* @param offset field/element offset
* @param delta the value to add
* @return the previous value
* @since 1.8
**/
@HotSpotIntrinsicCandidate
public final int getAndAddInt(Object o, long offset, int delta) {
 int v;
 do {
   v = getIntVolatile(o, offset);
 } while (!weakCompareAndSetInt(o, offset, v, v + delta));
 return v;
}

@HotSpotIntrinsicCandidate
public final boolean weakCompareAndSetInt(Object o, long offset,
                    int expected,
                    int x) {
 return compareAndSetInt(o, offset, expected, x);
}

如果obj内的value和expect相等,就证明没有其他线程改变过这个变量,那么就更新它为update,如果这一步的CAS没有成功,那就采用自旋的方式继续进行CAS操作。从代码中看着也是两个步骤,但其实在JNI里是借助于一个CPU指令完成的,实际还是原子操作。

ABA问题

产生ABA问题的原因

CAS需要在操作值的时候检查下值有没有发生变化,如果没有发生变化则更新,但是如果一个值原来是A,变成了B,又变成了A,那么使用CAS进行检查时会发现它的值没有发生变化,但是实际上却变化了。这就是CAS的ABA问题。

如何规避ABA问题

常用的办法是在更新数据的时候加入版本号,以版本号来控制更新。

Java并发的CAS原理与ABA问题的讲解

来源:https://blog.csdn.net/u012449363/article/details/86549823

标签:java,cas,aba
0
投稿

猜你喜欢

  • C++调用C#的DLL程序实现方法

    2023-02-04 13:58:16
  • Java中的main函数的详细介绍

    2021-10-03 16:09:16
  • 一篇文章带你入门Java之编程规范

    2022-02-25 16:18:40
  • C#深浅拷贝的深入解析

    2023-03-28 18:36:28
  • C#获取图片的后缀名解析

    2023-02-13 09:35:58
  • 一文带你搞懂Java中的泛型和通配符

    2023-12-10 16:15:07
  • Unity调用C++ dll实现打开双目相机

    2022-05-28 13:19:51
  • Android自定义Dialog实现加载对话框效果

    2022-04-19 12:16:06
  • Windows中使用C#为文件夹和文件编写密码锁的示例分享

    2023-09-27 06:27:23
  • Android树形控件绘制方法

    2022-09-05 01:50:55
  • WPF利用WindowChrome实现自定义窗口

    2021-06-08 07:33:55
  • spring boot 静态资源处理方法

    2022-07-14 22:12:42
  • Android Recyclerview实现多选,单选,全选,反选,批量删除的功能

    2021-12-10 21:57:24
  • Android studio 快速删除无用资源的方法

    2022-10-06 20:53:42
  • C语言时间函数之strftime()详解

    2023-06-26 02:42:32
  • 一文给你通俗易懂的讲解Java异常

    2021-12-20 14:40:56
  • java基础中异常及包归纳整理

    2022-11-08 17:46:02
  • c#中LINQ的基本用法(三)

    2022-11-29 11:06:31
  • JetBrains 产品输入激活码 Key is invalid 完美解决方案

    2023-11-08 08:57:55
  • springboot整合token的实现代码

    2023-11-10 19:02:03
  • asp之家 软件编程 m.aspxhome.com