我正在使用 Go 竞争检测(-race 参数),它检测到一些我认为不应该报告的竞争条件问题。我创建了这个示例代码来解释我的发现。请不要对此示例的目标发表评论,因为它除了解释问题之外没有其他目标。
这段代码:
var count int
func main() {
go update()
for {
fmt.Println(count)
time.Sleep(time.Second)
}
}
func update() {
for {
time.Sleep(time.Second)
count++
}
}
Run Code Online (Sandbox Code Playgroud)
报告有竞争条件。
虽然这段代码:
var count int
var mutex sync.RWMutex
func main() {
go update()
for {
mutex.RLock()
fmt.Println(count)
mutex.RUnlock()
time.Sleep(time.Second)
}
}
func update(){
for {
time.Sleep(time.Second)
mutex.Lock()
count++
mutex.Unlock()
}
}
Run Code Online (Sandbox Code Playgroud)
没有报告任何竞争条件问题。
我的问题是为什么?第一个代码中没有错误。main 函数正在读取另一个 go 例程正在更新的变量。这里没有潜在的隐藏错误。第二个代码互斥锁不提供任何不同的行为。
我哪里错了?
我很困惑,下面的代码片段完美吗?
import "sync"
import "sync/atomic"
var initialized uint32
var instance *singleton
var instance *singleton
var once sync.Once
func GetInstance() *singleton {
once.Do(func() {
instance = &singleton{}
})
return instance
}
Run Code Online (Sandbox Code Playgroud)
atomic.StoreUint32(&initialized, 1)会将实例刷新到所有CPU吗?我想我需要添加一个原子存储并加载,例如下面的代码片段
var instance *singleton
var once sync.Once
func GetInstance() *singleton {
once.Do(func() {
atomic.StorePointer(&instance, &singleton{})
})
return atomic.LoadPointer(&instance)
}
Run Code Online (Sandbox Code Playgroud)
我认为 Once.Do 只能保证函数 f 执行一次。并且atomic.StoreUint32(&o.done, 1)只是 o.done 的内存障碍。它不能确保instance全局可见
func (o *Once) Do(f func()) {
if atomic.LoadUint32(&o.done) == 1 {
return
}
// Slow-path.
o.m.Lock()
defer …Run Code Online (Sandbox Code Playgroud) 我在Go 1.12中有一个关于sync.Once()的问题。源代码如下:
// Because no call to Do returns until the one call to f returns, if f causes
// Do to be called, it will deadlock.
func (o *Once) Do(f func()) {
if atomic.LoadUint32(&o.done) == 1 {
return
}
// Slow-path.
o.m.Lock()
defer o.m.Unlock()
if o.done == 0 {
defer atomic.StoreUint32(&o.done, 1)
f()
}
}
Run Code Online (Sandbox Code Playgroud)
为什么不只使用一个uint32变量,然后对该变量执行CAS。它似乎更有效,并且不会导致死锁。
代码如下:
type Once uint32
func (o *Once) Do(f func()) {
if atomic.CompareAndSwapUint32((*uint32)(o), 0, 1) {
f()
}
}
Run Code Online (Sandbox Code Playgroud) 可能重复:
'synchronized'是什么意思?
Java同步的目的是什么,我应该如何使用它?