Cond
使协程进入阻塞状态,等待其它线程完成某件事后,使协程继续工作
var mu sync.Mutex
cond := sync.NewCond(&mu) //传入的是Locker接口,也就是不限定必须是Mutex,实现了Lock和Unlock就可以
sharedResource := 0
go func() {
mu.Lock()
for sharedResource == 0 {
cond.Wait() //符合条件进入等待,并且释放锁
}
fmt.Println("得到资源")
mu.Unlock()
}()
go func() {
time.Sleep(time.Millisecond * 3000) //等待1秒,明确感受到cond.Wait()会在等待期间释放锁的持有,不会因为上面的线程持有锁而导致这个线程无法进入锁(也就是不会导致死锁)
mu.Lock()
sharedResource = 1
fmt.Println("已设置资源")
cond.Signal() // 唤醒一个等待中的goroutine
mu.Unlock()
}()cond.Broadcast()是释放所有等待中的协程,上面的代码只有一个协程在等待用Signal就可以。
Once
声明的Once实例只会执行一次Do
var once sync.Once
once.Do(A)
once.Do(A) //什么也不会发生
once.Do(B) //什么也不会发生
func A() {
fmt.Println("A")
}
func B() {
fmt.Println("B")
}OnceFunc
创建一个只能调用一次的(没有返回值的)函数,即使多线程调用也只会调用一次
var fn = sync.OnceFunc(func() {
fmt.Println("OnceFunc")
})
for i := 0; i < 10; i++ {
go func() {
fn()
}()
}OnceValue
允许函数返回一个值,类型不限。fn只能被调一次,多次调用拿到的是首次调用返回的值
var fn = sync.OnceValue(func() string {
fmt.Println("OnceValue") //只会被执行一次
return "test content"
})
for i := 0; i < 10; i++ {
go func() {
fmt.Println(fn())
}()
}OnceValues
允许二个值
var fn = sync.OnceValues(func() (string, int) {
fmt.Println("OnceValues")
return "test content", 666
})
for i := 0; i < 10; i++ {
go func() {
fmt.Println(fn())
}()
}Map
线程安全的键值对
基本
var m sync.Map
m.Store("aa", "111")
fmt.Println(m.Load("aa")) //"111", true
m.Range(func(k, v interface{}) bool { //遍历所有键值
fmt.Println(k, v)
return true //返回false中断遍历
})
m.Delete("aa")
m.Clear()Swap
var m sync.Map
m.Store("aa", "111")
fmt.Println(m.Swap("aa", "333")) //"111", true,替换键的值并返因之前的值
fmt.Println(m.Load("aa")) //"333", true
fmt.Println(m.Swap("bb", 666)) // <nil>, false,在此之前健不存在
fmt.Println(m.Load("bb")) //"666", trueLoadAndDelete - 取值后删除键
var m sync.Map
m.Store("aa", "111")
val, loaded := m.LoadAndDelete("aa") //获取值然后移除对应的键
fmt.Println(val, loaded) // "111", true
val, loaded = m.Load("aa")
fmt.Println(val, loaded) // <nil>, falseLoadOrStore - 取或设
var m sync.Map
m.Store("aa", "111")
fmt.Println(m.LoadOrStore("aa", "222")) //"111", true,如果存在则取出,不存在则将值设置到键
fmt.Println(m.LoadOrStore("bb", "222")) // "222", false,将bb设为222CompareAndDelete
当前值是xxx则删除,不是则什么也不做
var m sync.Map
m.Store("aa", "111")
fmt.Println(m.CompareAndDelete("aa", "222")) //false
fmt.Println(m.CompareAndDelete("aa", "111")) //trueCompareAndSwap
var m sync.Map
m.Store("aa", "111")
fmt.Println(m.CompareAndSwap("aa", "222", "333")) //false, 当前值为222则更换为333
fmt.Println(m.CompareAndSwap("aa", "111", "444")) //true, 当前值为111则更换为444