【加锁】通过go的 mutex和atomic完成全局变量加锁

未加锁示例

  • CPU执行大致流程(不代表CPU实际执行流程): 加载total变量 -> 增加或减少total变量 -> 写入total变量, 当这个流程被多个协程同时操作且没有进行加锁,时最终的数据就会出现问题,大致示意图如下:
    CPU层面执行流程
var wg sync.WaitGroup
var total = 0
func add() {
	defer wg.Done()
	for i := 0; i < 10000; i++ {
		total++
	}
}
func sub() {
	defer wg.Done()
	for i := 0; i < 10000; i++ {
		total--
	}
}
func main() {
	wg.Add(2)
	go add()
	go sub()
	wg.Wait()
	fmt.Println(total)
}
// 输出:  -9902  (其实是随机变化的,无法预测的)

mux

  • 适合相对复杂场景下的加锁,如结构体等
var wg sync.WaitGroup
var lock sync.Mutex
var total = 0
func add() {
	defer wg.Done()
	for i := 0; i < 10000; i++ {
		lock.Lock()
		total++
		lock.Unlock()
	}
}
func sub() {
	defer wg.Done()
	for i := 0; i < 10000; i++ {
		lock.Lock()
		total--
		lock.Unlock()
	}
}
func main() {
	wg.Add(2)
	go add()
	go sub()
	wg.Wait()
	fmt.Println(total)
}

atomic

  • 性能更高, 适合相对简单的加锁, 如单个变量进行加锁的场景,
  • 本示例中相当于把add()方法的操作,当做一个原子操作来执行
var wg sync.WaitGroup
var total int32
func add() {
	defer wg.Done()
	for i := 0; i < 10000; i++ {
		atomic.AddInt32(&total,1)
	}
}
func sub() {
	defer wg.Done()
	for i := 0; i < 10000; i++ {
		atomic.AddInt32(&total,-1)
	}
}
func main() {
	wg.Add(2)
	go add()
	go sub()
	wg.Wait()
	fmt.Println(total)
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值