假设我声明了两个映射,并希望将其分配给错误组中的两个不同的goroutine。我不执行任何读/写操作。
我应该使用lock
保护分配操作还是可以忽略它?
UPD3:在Java Concurrency In Practice Brian Goetz's第I部分第3章Shared Objects
中,提到:
锁定不仅涉及互斥;这也是记忆 能见度。为确保所有线程看到最新值 共享的可变变量,读写线程必须 同步公用锁。
var (
mu sync.Mutex
one map[string]struct{}
two map[string]struct{}
)
g, gctx := errgroup.WithContext(ctx)
g.Go(func() error {
resp, err := invokeFirstService(gctx, request)
if err != nil {
return err
}
mu.Lock()
one = resp.One
mu.Unlock()
return nil
})
g.Go(func() error {
resp, err := invokeSecondService(gctx, request)
if err != nil {
return err
}
mu.Lock()
two = resp.Two
mu.Unlock()
return nil
})
if err := g.Wait(); err != nil {
return err
}
// UPD3: added lock and unlock section
m.Lock()
defer m.Unlock()
performAction(one, two)
UPD:添加了有关变量的更多上下文
UPD2:我有什么疑问:我们有3个goroutines-父类和错误组中的2个。无法保证在errgroup goroutine完成后,我们的父goroutine共享内存会获得最后更新,直到我们用内存屏障包装对共享内存的访问为止
答案 0 :(得分:3)
Group.Wait()
阻塞,直到返回了来自Group.Go()
方法的所有函数调用为止,因此这是一个同步点。这样可确保\agent_diag
在对performAction(one, two)
和one
的任何写操作完成之前不会启动,因此在您的示例中,互斥锁是不必要的。
two
如果您在写它们的goroutine同时运行时从其他goroutine访问g, gctx := errgroup.WithContext(ctx)
g.Go(func() error {
// ...
one = resp.One
return nil
})
g.Go(func() error {
// ...
two = resp.Two
return nil
})
if err := g.Wait(); err != nil {
return err
}
// Here you can access one and two safely:
performAction(one, two)
和one
,则是的,您需要锁定它们,例如:
two
还要注意,在上面的示例中,您可以使用sync.RWMutex
,在读取它们的goroutine中,RWMutex.RLock()
和RWMutex.RUnlock()
也足够。
答案 1 :(得分:0)
在这种情况下,只有一个goroutine可以访问地图。我认为您不需要锁。