V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
92pretty
V2EX  ›  Go 编程语言

下面代码中 f()会被重复执行吗?大佬帮忙解答一下~

  •  
  •   92pretty · 1 天前 · 946 次点击

    下面代码中 f()会被重复执行吗?

    package main
    
    import (
    	"fmt"
    	"sync"
    )
    
    type Once struct {
    	m    sync.Mutex
    	done uint32
    }
    
    func (o *Once) Do(f func()) {
    	if o.done == 1 {
    		return
    	}
    
    	o.m.Lock()
    	defer o.m.Unlock()
    
    	fmt.Println("bing: ", o.done)
    
    	if o.done == 0 {
    		o.done = 1
    		f()
    	}
    }
    
    func main() {
    	var once Once
    	wg := sync.WaitGroup{}
    
    	wg.Add(100)
    	for i := 0; i < 100; i++ {
    		go func() {
    			defer wg.Done()
    			once.Do(func() {
    				println("executed---------》 ")
    			})
    		}()
    	}
    	wg.Wait()
    }
    
    
    
    7 条回复    2026-01-08 16:08:33 +08:00
    ccpp132
        1
    ccpp132  
       1 天前
    不会
    YanSeven
        2
    YanSeven  
       1 天前
    额,你这个 demo 不都已经写好了,go run 一下立马知道。
    unused
        3
    unused  
       1 天前 via Android
    不会,但是不能保证 Do() 返回时 f() 已经执行
    supuwoerc
        4
    supuwoerc  
       14 小时 19 分钟前
    存在 data race ,你想要双重检查标识位,但是第一次检查没在加锁之后,是存在潜在问题的。

    问题出现在 done uint32 的读写并不是原子的,你需要换成原子读写,你这段代码和 sync.Once 的区别就是这里。

    ```
    func (o *Once) Do(f func()) {
    if atomic.LoadUint32(&o.done) == 1 {
    return
    }

    o.m.Lock()
    defer o.m.Unlock()

    fmt.Println("bing: ", o.done)

    if atomic.LoadUint32(&o.done) == 0 {
    atomic.StoreUint32(&o.done, 1)
    f()
    }
    }
    ```
    bv
        5
    bv  
       14 小时 18 分钟前
    不会,但 if o.done == 1 { return } 存在 data race 。
    92pretty
        6
    92pretty  
    OP
       13 小时 51 分钟前
    @supuwoerc 嗯嗯 弄清楚了,是这个理。happens before 的问题。f()可能会初始化一些配置、链接啥等,但是还没执行完,done 已经被设置为 1 了,后续进入的请求会直接 return , 认为 f()已经执行完成
    supuwoerc
        7
    supuwoerc  
       13 小时 43 分钟前
    @supuwoerc 是的,需要补充下,atomic.StoreUint32(&o.done, 1)应该 defer 执行,避免 happens before
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   Solana   ·   971 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 20ms · UTC 21:51 · PVG 05:51 · LAX 13:51 · JFK 16:51
    ♥ Do have faith in what you're doing.