其他分享
首页 > 其他分享> > Golang sync/atomic包——原子操作

Golang sync/atomic包——原子操作

作者:互联网

1、概述

1.1 基本概念

原子性:一个或多个操作在CPU的执行过程中不被中断的特性,称为原子性。这些操作对外表现成一个不可分割的整体,他们要么都执行,要么都不执行,外界不会看到他们只执行到一半的状态。

原子操作:进行过程中不能被中断的操作,原子操作由底层硬件支持,而锁则是由操作系统提供的API实现,若实现相同的功能,前者通常会更有效率

Golang 中的原子操作:sync/atomic包

能够进行原子操作的类型:int32, int64, uint32, uint64, uintptr, unsafe.Pointer

五种操作函数:增或减、比较并交换、载入、存储、交换

原子操作比锁更为高效。

1.2 原子操作 vs 锁

1.3 五种操作

1.4 最小案例

package main

import (
	"sync"
	"fmt"
)

var count int

func add(wg *sync.WaitGroup) {
	defer wg.Done()
	count++
}

func main() {
	wg := sync.WaitGroup{}
	wg.Add(1000)
	for i := 0; i < 1000; i++ {
		go add(&wg)
	}
	wg.Wait()
	fmt.Println(count)
}

count不会等于1000,因为count++这一步实际是三个操作:

因此就会出现多个goroutine读取到相同的数值,然后更新同样的数值到内存,导致最终结果比预期少。

2、sync/atomic包使用

Go语言提供的原子操作都是非入侵式的,由标准库中sync/aotomic中的众多函数代表

atomic包中支持六种类型

对于每一种类型,提供了五类原子操作:

Go sync/atomic api

因此第一部分的案例可以修改如下,即可通过

// 修改方式1
func add(wg *sync.WaitGroup) {
	defer wg.Done()
	atomic.AddInt32(&count, 1)
}

// 修改方式2
func add(wg *sync.WaitGroup) {
	defer wg.Done()
	for {
		if atomic.CompareAndSwapInt32(&count, count, count+1) {
			break
		}
	}
}

参考:https://juejin.cn/post/6844904053042839560

参考:https://blog.csdn.net/elihe2011/article/details/109157797

标签:count,wg,addr,sync,原子,Golang,atomic,操作
来源: https://www.cnblogs.com/zhangmingcheng/p/15819668.html