在 Go 语言中,sync/atomic 包提供了一系列的原子操作,这些操作在并发环境中非常有用,因为它们可以保证在多个 goroutine 之间对变量的操作是安全的,不会被其他 goroutine 的操作打断。以下是一些常用的原子操作:
LoadInt32,LoadInt,LoadUint32,LoadUint,LoadUintptr,LoadPointer:这些函数可以原子地加载指定地址的值。StoreInt32,StoreInt,StoreUint32,StoreUint,StoreUintptr,StorePointer:这些函数可以原子地将值存储到指定地址。AddInt32,AddInt,AddUint32,AddUint,AddUintptr:这些函数可以原子地给指定地址的值增加一个增量。SwapInt32,SwapInt,SwapUint32,SwapUint,SwapUintptr,SwapPointer:这些函数可以原子地交换新旧值。CompareAndSwapInt32,CompareAndSwapInt,CompareAndSwapUint32,CompareAndSwapUint,CompareAndSwapUintptr,CompareAndSwapPointer:这些函数可以原子地比较并交换值。AndInt32,AndInt,AndUint32,AndUint,AndUintptr:原子地对地址的值执行位与操作。OrInt32,OrInt,OrUint32,OrUint,OrUintptr:原子地对地址的值执行位或操作。Pointer类型提供了对指针的原子操作,如Load,Store,Swap,CompareAndSwap。Bool类型提供了对布尔值的原子操作,如Load,Store,Swap,CompareAndSwap。Value类型可以用于存储任何类型的值,并提供原子的Load和Store操作。
原子加载和存储:
原子增加和减少:
原子交换:
比较并交换:
原子位操作(Go 1.23 新增):
原子指针操作(Go 1.19 新增):
原子布尔操作(Go 1.19 新增):
通用原子操作(Go 1.4 新增):
使用 sync/atomic 包可以避免在并发程序中使用互斥锁,从而提高性能。例如,如果你有一个共享的计数器,你可以使用 atomic.AddInt32 来安全地增加它的值,而不需要使用互斥锁。
这里有一个使用 sync/atomic 的简单例子:
import (
"sync"
"sync/atomic"
)
func main() {
var wg sync.WaitGroup
var counter uint32
for i := 0; i < 1000; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for j := 0; j < 100; j++ {
atomic.AddUint32(&counter, 1)
}
}()
}
wg.Wait()
fmt.Println("Counter:", atomic.LoadUint32(&counter))
}
在这个例子中,我们创建了1000个 goroutine,每个 goroutine 将计数器增加100次。使用 atomic.AddUint32 确保了即使在并发环境下,计数器的值也是准确的。