Golang 并发原语 Sync Once

Once 保证操作只执行一次

  • 适用于一些单例、配置的加载等

内部数据结构

go 复制代码
type Once struct {
    done atomic.Uint32
    m    Mutex
}
  • done 用于标识操作是否已经完成只有01
  • m 互斥锁

核心方法

  • Do

    scss 复制代码
    func (o *Once) Do(f func()) {
        if o.done.Load() == 0 {
           o.doSlow(f)
        }
    }
    func (o *Once) doSlow(f func()) {
        o.m.Lock()
        defer o.m.Unlock()
        if o.done.Load() == 0 {
           defer o.done.Store(1)
           f()
        }
    }
  • 原子加载done值是否为0

  • 如果等于0说明f func()并没有被初始化

  • 进入doSlow方法

  • 加锁,然后再次原子加载done值是否为0。这里进行可一个double check,确保当前done的值没有被修改

  • 执行f func(),然后将done标记为1

once这个并发原底层代码非常简洁,也很好理解。

相关推荐
不爱笑的良田1 小时前
从零开始的云原生之旅(十一):压测实战:验证弹性伸缩效果
云原生·容器·kubernetes·go·压力测试·k6
橙子家4 小时前
Serilog 日志库简单实践(二):控制台与调试 Sinks(.net8)
后端
想不明白的过度思考者5 小时前
Rust——异步递归深度指南:从问题到解决方案
开发语言·后端·rust
ConardLi6 小时前
Easy Dataset 已经突破 11.5K Star,这次又带来多项功能更新!
前端·javascript·后端
芒克芒克6 小时前
ssm框架之Spring(上)
java·后端·spring
冒泡的肥皂6 小时前
MVCC初学demo(二
数据库·后端·mysql
追逐时光者6 小时前
一款基于 .NET WinForm 开源、轻量且功能强大的节点编辑器,采用纯 GDI+ 绘制无任何依赖库仅仅100+Kb
后端·.net
鬼火儿6 小时前
1.2 redis7.0.4安装与配置开机自启动
java·后端
逻极6 小时前
Rust数据类型(上):标量类型全解析
开发语言·后端·rust
百锦再7 小时前
第2章 第一个Rust程序
java·开发语言·后端·rust·eclipse·tomcat·hibernate