在 Go 语言中,sync/atomic 包提供了底层的原子内存操作,这些操作对于实现同步算法非常有用。这些函数需要谨慎使用,以确保正确性。对于大多数同步需求,推荐使用通道或者 sync 包中的设施。Go 的内存模型保证了原子操作的执行顺序,就像 C++ 中的顺序一致性原子操作和 Java 中的 volatile 变量一样 。

sync/atomic 包提供的操作包括:

  1. 原子整数操作:如 AddInt32CompareAndSwapInt32 等,用于对32位或位整型变量进行原子加减、交换、加载、存储等操作。
  2. 原子指针操作:如 SwapPointerStorePointer 等,用于对指针进行原子交换、存储等操作。
  3. 原子标量函数:如 LoadUint32StoreUint32 等,提供对各种宽度(32位、位)和类型的标量值进行原子加载和存储。

使用 sync/atomic 时,需要注意以下几点:

  • 始终使用原子操作处理共享变量,以避免数据竞争。
  • 理解原子操作的语义,对于复杂的同步逻辑,可能需要结合使用其他同步原语。
  • 熟悉并遵循原子操作的内存排序约束,以确保数据的正确可见性 。

例如,如果你想要原子地增加一个 uint32 变量,你可以使用 AddUint32 函数:

import "sync/atomic"

var counter uint32
func increment() {
    atomic.AddUint32(&counter, 1)
}
func getCounter() uint32 {
    return atomic.LoadUint32(&counter)
}

如果你需要进行更复杂的操作,比如比较并交换,你可以使用 CompareAndSwapUint32 函数:

func compareAndSwap(old, new uint32) (swapped bool) {
    return atomic.CompareAndSwapUint32(&counter, old, new)
}

此外,sync/atomic 包还提供了对 intuintuintptr 等类型的原子操作。对于指针类型的原子操作,可以使用 SwapPointerCompareAndSwapPointer 等函数。

在某些情况下,你可能需要对整数值执行按位与、或、非等操作,sync/atomic 包从 Go 1.23 版本开始提供了这样的函数,例如 AndInt32OrInt32 等 。

总的来说,sync/atomic 包为 Go 语言提供了强大的原子操作支持,是构建并发安全程序的重要工具。