atomic 轻量级锁

作者:matrix 被围观: 3 次 发布时间:2026-04-30 分类:Golang | 无评论 »

atomic 实际上就是一种“轻量级锁”的实现,但更准确地说,它是“无锁(lock-free)并发”的一种实现方式——直接使用 CPU 的原子指令来保证数据的并发安全

atomic使用底层硬件实现的,没有锁但是实现了锁的功能,不像Golang中Mutex、RWMutex锁使用的是软件层面实现开销大。

sync/atomic锁类型

包还提供了多个类型

布尔值

类型 描述
atomic.Bool 原子布尔值(true/false)

数值类型(适合计数器、状态码等)

类型 描述 方法示例
atomic.Int32 原子 32 位整数 Add(), Load(), Store()
atomic.Int64 原子 64 位整数 同上
atomic.Uint32 原子无符号 32 位整数 同上
atomic.Uint64 原子无符号 64 位整数 同上
atomic.Uintptr 原子 uintptr(指针偏移等) Swap(), CompareAndSwap()

这些数值类型背后都是通过 atomic.AddInt64atomic.LoadInt64 等封装来的。


任意值类型(适合共享配置、数据对象等)

类型 描述
atomic.Value 通用的线程安全容器,支持任意类型的值存取

Example

看着以为简单,实际使用还是得注意

atomic.Bool

var flag atomic.Bool

func work(name string) {
    // if !flag.Load() // 获取值。 如果这样 输出结果依然全是第一次进入 没有达到锁的效果
    if flag.CompareAndSwap(false, true) {
        fmt.Printf("name:%v, flag is false(第一次进入)\n", name)
        time.Sleep(100 * time.Millisecond) // 模拟耗时
        flag.Store(true) //写入值
        return
    }
    fmt.Printf("name:%v, flag is true\n", name)
}
func main() {
    for i := 0; i < 10; i++ {
        go work(fmt.Sprint("goroutine:", i))
    }
    time.Sleep(time.Second * 5)
}

// output:
// name:goroutine:9, flag is true
// name:goroutine:3, flag is false(第一次进入)
// name:goroutine:8, flag is true
// name:goroutine:1, flag is true
// name:goroutine:7, flag is true
// name:goroutine:4, flag is true
// name:goroutine:6, flag is true
// name:goroutine:2, flag is true
// name:goroutine:5, flag is true
// name:goroutine:0, flag is true

关键是CompareAndSwap方法,只有第一个 GOroutine 做某事(比如只执行一次初始化),那就必须用 CompareAndSwap()

CompareAndSwap(false, true): 判断当前值是否 false,且设置 true 成功

atomic.Int64

并发计数器

var flag atomic.Int64

func work(addval int64) {
    flag.Add(addval)
}
func main() {

    for i := 0; i < 10000; i++ {
        go work(int64(1))
    }
    time.Sleep(time.Second * 1)
    fmt.Println(flag.Load())
}

//output:
// 10000

atomic.Value

允许定义自定义结构体

var flag atomic.Value

type Res struct {
    v bool
}

func work(name int) {
    // if flag.Load() != nil && flag.Load().(Res).v == false // 可能存在竞态问题,不能使用!!!
    if flag.Load() != nil && flag.CompareAndSwap(Res{v: false}, Res{v: true}) { // 使用CompareAndSwap 才能保证原子性
        //flag.Store(Res{v: true}) // 多余操作,CompareAndSwap内部会把Res{v: true}值赋上
        time.Sleep(time.Second * 1)
        fmt.Printf("name:%d 第一次执行\n", name)
        return
    }
    fmt.Printf("name:%d 已操作\n", name)

}
func main() {
    flag.Store(Res{v: false})
    for i := 0; i < 10; i++ {
        go work(i)
    }
    time.Sleep(time.Second * 2)
    // fmt.Println(flag.Load())
    fmt.Printf("%T\n", flag)
}

flag.CompareAndSwap(old, new) 第一个参数old,就表示期望获取的状态锁(false),获取到之后会把flag赋值为new

其他文章:
本文固定链接:https://www.hhtjim.com/atomic.html
matrix
本文章由 matrix 于2026年04月30日发布在Golang分类下,目前没有通告,你可以至底部留下评论。
转载请注明:atomic 轻量级锁-HHTjim'S 部落格
关键字:,

添加新评论 »

 🙈 😱 😂 😛 😭 😳 😀 😆 👿 😉 😯 😮 😕 😎 😐 😥 😡 😈 💡

插入图片