一架梯子,一头程序猿,仰望星空!

golang atomic原子操作


atomic包提供了底层的原子级内存操作,对于同步算法的实现很有用。

atomic原子操作主要用于并发环境下,无须加锁对整数进行安全的加减、比较、读取操作。

atomic原子操作支持的数据类型:

  • int32
  • int64
  • Uint32
  • Uint64

1.例子

// 访问量计数
var count int64 = 0

// 对count变量进行原子加 1
// 原子操作可以在并发环境安全的执行
atomic.AddInt64(&count, 1)

// 对count变量原子减去10
atomic.AddInt64(&count, -10)

// 原子读取count变量的内容
pv := atomic.LoadInt64(&count)

2.atomic常用函数

2.1. LoadInt32

函数定义:

func LoadInt32(addr *int32) (val int32)

LoadInt32原子性的获取*addr的值。

LoadInt64,LoadUint32,LoadUint64序列函数用法类似,区别就是数据类型不同。

例子:

var count int32 = 0

// 原子读取count变量的内容
pv := atomic.LoadInt32(&count)

2.2. StoreInt32

函数定义:

func StoreInt32(addr *int32, val int32)

StoreInt32原子性的将val的值保存到*addr。

StoreInt64、StoreUint32、StoreUint64序列函数用法类似,区别就是数据类型不同

例子:

var count int32 = 0

// 安全的将100保存到count变量中
atomic.StoreInt32(&count, 100)

2.3. AddInt32

函数定义:

func AddInt32(addr *int32, delta int32) (new int32)

AddInt32原子性的将delta的值添加到*addr并返回新值。

AddInt64、AddUint32、AddUint64序列函数用法类似,区别就是数据类型不同

AddXXX 系列函数实现加法操作,在原子性上等价于:

*addr += delta
return *addr

例子:

var count int32 = 0

// 对count变量进行原子加 1, 并且返回新值
newCount := atomic.AddInt32(&count, 1)

2.4. SwapInt32

函数定义:

func SwapInt32(addr *int32, new int32) (old int32)

SwapInt32原子性的将新值保存到*addr并返回旧值。

SwapInt64、SwapUint32、SwapUint64序列函数用法类似,区别就是数据类型不同。

SwapXXX序列函数操作在原子性上等价于:

old = *addr
*addr = new
return old

例子:

var count int32 = 0

//  将200保存到count中, 并且返回旧的值
oldCount := atomic.SwapInt32(&count, 200)

2.5. CompareAndSwapInt32

函数定义:

func CompareAndSwapInt32(addr *int32, old, new int32) (swapped bool)

CompareAndSwapInt32原子性的比较addr和old,如果相同则将new赋值给addr并返回真。

CompareAndSwapInt64、CompareAndSwapUint32、CompareAndSwapUint64序列函数用法类似,区别就是数据类型不同。

CompareAndSwapXXX系列函数实现的比较-交换操作,在原子性上等价于:

if *addr == old {
	*addr = new
	return true
}
return false

例子:

var count int32 = 0

//  如果count变量的值为0,才将100保存到变量中,保存成功返回true,反之false
ok := atomic.CompareAndSwapInt32(&count, 0, 100)