CAS乐观锁的ABA问题

CAS

1.CAS 原理

CAS 机制当中使用了 3 个基本操作数:内存地址 V,旧的预期值 A,要修改的新值 B。
更新一个变量的时候,只有当变量的预期值 A 和内存地址 V 当中的实际值相同时,才会将内存地址 V 对应的值修改为 B。

CAS 的原理就是预期值 A 与内存中的值相比较,如果相同则将内存中的值改变成新值 B。这样比较有两类:

  • 第一类:如果操作的是基本变量,则比较的是 值 是否相等。

  • 第二类:如果操作的是对象的引用,则比较的是对象在 内存的地址 是否相等。

2.CAS 缺点

  • CPU 开销较大,多线程反复尝试更新某一个变量的时候容易出现;
  • 不能保证代码块的原子性,只能保证变量的原子性操作;
  • ABA 问题。

ABA 问题

1.ABA问题

线程 1 准备利用 CAS 修改变量值 A,但是在修改之前,其他线程已经将 A 变成了 B,然后又变成 A,即 A->B->A, 线程 1 执行 CAS 的时候发现仍然为 A,所以 CAS 会操作成功,但是其实目前这个 A 已经是其他线程修改的了,但是线程 1 并不知道,最终内存值变成了 B,这就导致了 ABA 问题。

2.解决

JDK 中解决 CAS 中 ABA 问题有两种解决方案

(一) boolean 标记:只能记录它改变过,不能记录改变的次数

通过添加一个 boolean 类型标记和操作的对象封装成 Pair ,这个boolean类型标记是volatile类型的,保证所有线程的内存可见性,当有线程修改变量的时候,boolean标记就会记录,当CAS来比较的时候会同时比较这个标记,就会知道是否被更改了,从而判断是否执行CAS。

(二)int标记:记录改变的次数

仅仅用一个 boolean 去标记,如果想知道被操作对象更改了几次,就无法处理了,因为它仅仅用一个 boolean 去标记只能判断是否被更改过,但是如果是int类型,不仅仅可以判断是否更改,也可以判断更改过几次。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章