Go语言核心36讲(Go语言实战与应用八)--学习笔记

30 | 原子操作(下)

我们接着上一篇文章的内容继续聊,上一篇我们提到了,sync/atomic包中的函数可以做的原子操作有:加法(add)、比较并交换(compare and swap,简称 CAS)、加载(load)、存储(store)和交换(swap)。并且以此衍生出了两个问题。

今天我们继续来看第三个衍生问题: 比较并交换操作与交换操作相比有什么不同?优势在哪里?

回答是:比较并交换操作即 CAS 操作,是有条件的交换操作,只有在条件满足的情况下才会进行值的交换。

所谓的交换指的是,把新值赋给变量,并返回变量的旧值。

在进行 CAS 操作的时候,函数会先判断被操作变量的当前值,是否与我们预期的旧值相等。如果相等,它就把新值赋给该变量,并返回true以表明交换操作已进行;否则就忽略交换操作,并返回false。

可以看到,CAS 操作并不是单一的操作,而是一种操作组合。这与其他的原子操作都不同。正因为如此,它的用途要更广泛一些。例如,我们将它与for语句联用就可以实现一种简易的自旋锁(spinlock)。

for {
 if atomic.CompareAndSwapInt32(&num2, 10, 0) {
  fmt.Println("The second number has gone to zero.")
  break
 }
 time.Sleep(time.Millisecond * 500)
}

在for语句中的 CAS 操作可以不停地检查某个需要满足的条件,一旦条件满足就退出for循环。这就相当于,只要条件未被满足,当前的流程就会被一直“阻塞”在这里。

这在效果上与互斥锁有些类似。不过,它们的适用场景是不同的。我们在使用互斥锁的时候,总是假设共享资源的状态会被其他的 goroutine 频繁地改变。

而for语句加 CAS 操作的假设往往是:共享资源状态的改变并不频繁,或者,它的状态总会变成期望的那样。这是一种更加乐观,或者说更加宽松的做法。

package main

import (
	"fmt"
	"sync/atomic"
	"time"
)

func main() {
	// 第三个衍生问题的示例。
	forAndCAS1()
	fmt.Println()
	forAndCAS2()
}

// forAndCAS1 用于展示简易的自旋锁。
func forAndCAS1() {
	sign := make(chan struct{}, 2)
	num := int32(0)
	fmt.Printf("The number: %d\n", num)
	go func() { // 定时增加num的值。
		defer func() {
			sign <- struct{}{}
		}()
		for {
			time.Sleep(time.Millisecond * 500)
			newNum := atomic.AddInt32(&num, 2)
			fmt.Printf("The number: %d\n", newNum)
			if newNum == 10 {
				break
			}
		}
	}()
	go func() { // 定时检查num的值,如果等于10就将其归零。
		defer func() {
			sign <- struct{}{}
		}()
		for {
			if atomic.CompareAndSwapInt32(&num, 10, 0) {
				fmt.Println("The number has gone to zero.")
				break
			}
			time.Sleep(time.Millisecond * 500)
		}
	}()
	<-sign
	<-sign
}

// forAndCAS2 用于展示一种简易的(且更加宽松的)互斥锁的模拟。
func forAndCAS2() {
	sign :
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值