在 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:这些函数可以原子地比较并交换值。

    原子位操作(Go 1.23 新增):

    • AndInt32, AndInt, AndUint32, AndUint, AndUintptr:原子地对地址的值执行位与操作。
    • OrInt32, OrInt, OrUint32, OrUint, OrUintptr:原子地对地址的值执行位或操作。

    原子指针操作(Go 1.19 新增):

    • Pointer 类型提供了对指针的原子操作,如 Load, Store, Swap, CompareAndSwap

    原子布尔操作(Go 1.19 新增):

    • Bool 类型提供了对布尔值的原子操作,如 Load, Store, Swap, CompareAndSwap

    通用原子操作(Go 1.4 新增):

    • Value 类型可以用于存储任何类型的值,并提供原子的 LoadStore 操作。

使用 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 确保了即使在并发环境下,计数器的值也是准确的。