aba问题

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

aba问题
ABA 问题是指在进行 CAS 操作的时候,某个线程将一个变量的值从A 变成 B,再从 B 变成 A,其他线程会认为变量的值没有发生改变,于是正常进行 CAS 操作。

CAS(Compare And Swap):
CAS 就是“比较并交换”,它有三个操作数:内存值 V、旧的预期值A、准备设置的新值 C。

CAS 最核心的思路就是,当且仅当预期值 A 和当前的内存值 V 相同时,才将内存值修改为 B。

例如,“变量”的初始值为 A,“线程1”、“线程2”对“变量”进行以下操作:
“线程1”进行 CAS,记录“旧的预期值”为 A
“线程1”被挂起,“线程2”执行
“线程2”将“变量”的值改为 B
“线程2”再次将“变量”的值改为 A
“线程1”被唤醒,继续执行
“线程1”准备将“变量”的值改为 B
“线程1”进行 CAS,对比“变量”的“内存值”和“旧的预期值”都为 A
“线程1”进行 CAS,将“变量”的值改为“准备设置的新值”:C
ABA 问题的影响
例子中,“线程1”的 CAS 执行成功,但实际上“变量”被“线
程2”改变过,经历了 A->B->A 的过程,然而“线程1”的 CAS 不能察觉到这个改变。

CAS 并不能检测出“变量”在此期间值是不是被修改过,只能检测出当前的值和最初的值是否一样。

看到这里,也许你会觉得这并没有什么问题,“变量”的值符合预期。

举个例子,有一个链表的初始状态为:A->B->C->D,“线程1”试图通过 CAS 将链表中的 A 改成 Z,进行以下操作:
“线程1”进行 CAS,记录链表的首节点“旧的预期值”为 A (链表的状态:A->B->C->D)
“线程1”被挂起,“线程2”执行
(链表的状态:A->B->C->D)
“线程2”将链表中的 B 删除
(链表的状态:A->C->D)
“线程1”被唤醒,继续执行
(链表的状态:A->C->D)
“线程1”准备将链表中的 A 改为 Z
(链表的状态:A->C->D)
“线程1”进行 CAS,对比链表首节点的“内存值”和“旧的预期值”都为 A
(链表的状态:A->C->D)
“线程1”进行 CAS,将链表中的 A 改为“准备设置的新值”:C (链表的状态:Z->C->D)
在这个例子中,CAS 只能检测到链表的首节点的内存地址是否发生过改变,并不能检测到链表的结构是否改变。

如何解决 ABA 问题
为了解决 ABA 问题,增加了版本号的机制来记录变化,“内存值 V”每次发生改变的时候,都把版本号 + 1。

例如,在第一个例子的基础上,我们加上版本号。

“变量”的初始值为 A,“线程1”、“线程2”对“变量”进行以下操作:
“线程1”进行 CAS,记录“旧的预期值”为 A 和版本号为 0 (“变量”的版本号:0)
“线程1”被挂起,“线程2”执行
(“变量”的版本号:0)
“线程2”将“变量”的值改为 B,“变量”的版本号 + 1 (“变量”的版本号:1)
“线程2”再次将“变量”的值改为 A,“变量”的版本号 + 1 (“变量”的版本号:2)
“线程1”被唤醒,继续执行
(“变量”的版本号:2)
“线程1”准备将“变量”的值改为 B
(“变量”的版本号:2)
“线程1”进行 CAS,对比“变量”的“内存值”和“旧的预期值”都为 A
(“变量”的版本号:2)
“线程1”进行 CAS,对比版本号 0 和 2 不相等“线程1”更新失败。

相关文档
最新文档