这种golangs原子包的使用是否正确?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了这种golangs原子包的使用是否正确?相关的知识,希望对你有一定的参考价值。
我有两种方法的类型; Add
和Close
。同时访问Add
方法,它应检查是否曾调用过Close
。
type foo struct {
closed bool
}
func (f *foo) Close() error {
f.closed = true
...
}
func (f *foo) Add(...) error {
if f.closed {
return ErrClosed
}
...
}
这是一场竞争条件吧?
那么在这种情况下使用原子存储/加载是否有意义?
type foo struct {
closed int32
}
func (f *foo) Close() error {
atomic.StoreInt32(&f.closed, 1)
...
}
func (f *foo) Add(...) error {
if atomic.LoadInt32(&f.closed) == 1 {
return ErrClosed
}
...
}
或者一个频道是一个更惯用的方式来做到这一点:
type foo struct {
closed chan struct{}
}
func NewFoo() *foo {
return &foo{make(chan struct{})}
}
func (f *foo) isClosed() bool {
select {
case <-f.closed:
return true
default:
}
return false
}
func (f *foo) Close() error {
close(f.closed)
...
}
func (f *foo) Add(...) error {
if f.isClosed() {
return ErrClosed
}
...
}
编辑:
谢谢你的评论,我最终得到了这个。
type foo struct {
closed bool
closeLock sync.RWMutex
}
func (f *foo) Close() error {
f.closeLock.Lock()
defer f.closeLock.Unlock()
f.closed = true
...
}
func (f *foo) Add(...) error {
f.closeLock.RLock()
defer f.closeLock.RUnlock()
if f.closed {
return ErrClosed
}
...
}
答案
这是一场竞争条件吧?
如果Close()
与Add()
同时被召唤,那它确实是一场数据竞赛。 “竞争条件”是一个更通用的术语,原子只能阻止数据竞争,而不是所有竞争条件。并发的定义基于https://golang.org/ref/mem但是如果没有协调并且它是从多个goroutine完成的,那么它是并发的。
那么在这种情况下使用原子存储/加载是否有意义?
严格来说,它不太可能有意义。你写的是数据竞争免费。然而,原子是棘手的。例如,如果你现在向这个结构添加了一个原子int64,它将在x86-32机器上有数据条,而不是64位对齐,而如果你先订购int64,它就不会。原子药可能很危险,应谨慎使用。
或者一个频道是一种更为自我的方式来做到这一点
是!您还可以使用sync.Mutex甚至sync.RWMutex。除非您真正编写sync.Mutex实现,否则Atomics是一种优化。您应该始终在第一个实现中避免它们。如果您有可测量的锁争用,那么您可以考虑使用原子。只是要非常小心,并意识到很有可能弄乱它。
以上是关于这种golangs原子包的使用是否正确?的主要内容,如果未能解决你的问题,请参考以下文章