cas 保存用户信息_Go是如何实现乐观锁(CAS理论)

3fb3ecfed7f91968c143c7553e3a4ca2.png

我们在之前的Go锁源码的文章中中介绍了CAS理论。

张麒麟:Go互斥锁源码解析​zhuanlan.zhihu.com
1a232b1f1ac8b2aaf3686e9dd63edeac.png

比较并交换(compare and swap, CAS),是原子操作的一种,可用于在多线程编程中实现不被打断的数据交换操作,从而避免多线程同时改写某一数据时由于执行顺序不确定性以及中断的不可预知性产生的数据不一致问题。 该操作通过将内存中的值与指定数据进行比较,当数值一样时将内存中的数据替换为新的值。

究竟CAS理论是如何设计的

一、CAS是如何运行的


我们有两个goroutineA和goroutineB,接下来我们简称 A 和 B, 共享资源称为C

    1. A 和 B 均保存 C 当前的值
    2. A 尝试使用CAS(56,53)更新C的值
    3. C目前为56,可以更新,然后更新成功
    4. B尝试使用CAS(56,53)更新C的值
    5. C已经为53,更新失败。

17fd21a245c631da864934bb6e7ed4d9.png

二、Go中的CAS源码

// CompareAndSwapUint32 executes the compare-and-swap operation for a uint32 value.
func CompareAndSwapUint32(addr *uint32, old, new uint32) (swapped bool)


实际代码文件在

Go / src / runtime / internal / atomic / asm_amd.s文件中

TEXT runtime∕internal∕atomic·Cas64(SB), NOSPLIT, $0-25
 MOVQ ptr+0(FP), BX
 MOVQ old+8(FP), AX
 MOVQ new+16(FP), CX
 LOCK
 CMPXCHGQ CX, 0(BX)
 SETEQ ret+24(FP)
 RET


其中我们可以看作
lock(一个命令前缀,在这里用于CMPXCHGQ)可以锁住总线保证多次内存操作的原子性。
然后执行CMPXCHGQ

cmpxchg %cx, %bx;如果AX与BX相等,则CX送BX且ZF置1;否则BX送CX,且ZF清0
    1. 拿AX(old) 与 BX(共享数据ptr) 做对比。
    2. 相等,则修改BX(共享数据ptr),状态码ZX设置为 1 。
    3. 不相等,则将CX(new)置为目前BX(共享数据ptr)的值, 状态码ZX设置为 0

三、CAS的缺陷

    1. CAS在共享资源竞争比较激烈的时候,每个goroutine会容易处于自旋状态,影响效率,在竞争激烈的时候推荐使用锁。
    2. 无法解决ABA问题
      ABA问题是无锁结构实现中常见的一种问题,可基本表述为:
进程P1读取了一个数值A
P1被挂起(时间片耗尽、中断等),进程P2开始执行
P2修改数值A为数值B,然后又修改回A
P1被唤醒,比较后发现数值A没有变化,程序继续执行。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值