62 строки
1 КиБ
Go
62 строки
1 КиБ
Go
package sync_test
|
|
|
|
import (
|
|
"sync"
|
|
"testing"
|
|
)
|
|
|
|
// TestOnceUncontended tests Once on a single goroutine.
|
|
func TestOnceUncontended(t *testing.T) {
|
|
var once sync.Once
|
|
{
|
|
var ran bool
|
|
once.Do(func() {
|
|
ran = true
|
|
})
|
|
if !ran {
|
|
t.Error("first call to Do did not run")
|
|
}
|
|
}
|
|
{
|
|
var ran bool
|
|
once.Do(func() {
|
|
ran = true
|
|
})
|
|
if ran {
|
|
t.Error("second call to Do ran")
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestOnceConcurrent tests multiple concurrent invocations of sync.Once.
|
|
func TestOnceConcurrent(t *testing.T) {
|
|
var once sync.Once
|
|
var mu sync.Mutex
|
|
mu.Lock()
|
|
var ran bool
|
|
var ranTwice bool
|
|
once.Do(func() {
|
|
ran = true
|
|
|
|
// Start a goroutine and (approximately) wait for it to enter the call to Do.
|
|
var startWait sync.Mutex
|
|
startWait.Lock()
|
|
go func() {
|
|
startWait.Unlock()
|
|
once.Do(func() {
|
|
ranTwice = true
|
|
})
|
|
mu.Unlock()
|
|
}()
|
|
startWait.Lock()
|
|
})
|
|
if !ran {
|
|
t.Error("first call to Do did not run")
|
|
}
|
|
|
|
// Wait for the goroutine to finish.
|
|
mu.Lock()
|
|
if ranTwice {
|
|
t.Error("second concurrent call to Once also ran")
|
|
}
|
|
}
|