sync.RWMutex | sync.WaitGroup | sync.NewCond | sync.Once | sync.Map |
package main import ( "fmt" "sync" "time" ) func main() { rw := sync.RWMutex{} //可以让多个协程同时读取某对象 //初始值为解锁状态,通常作为其他结构体的匿名字段使用 //可以安全的在多个协程中并行使用 rw.Lock() // 设置为写状态,禁止其他协程读取或写入 rw.Unlock() // 解锁状态,如果未被锁定---> panic rw.RLock() // 设置为写状态,禁止其他协程写入;但是可以读取 rw.RUnlock() // 解锁状态,如果未被锁定---> panic rw.RLocker() // 返回一个互斥锁,将rw.Rlock和rw.RUnlock封装过程一个Locker接口 wg := sync.WaitGroup{} wg.Add(1) // 计数器加1,必须是正数 wg.Done() // 计数器减1,直到归零,如果小于0,则该操作会引发panic wg.Wait() //条件等待,直到信号发送过来 cond := sync.NewCond(new(sync.Mutex)) // 用一把锁 for i := 0; i < 2; i++ { go func() { cond.L.Lock() cond.Wait() // 等待发送信号,消费一个信号 fmt.Printf("%p\t%v\n", cond.L, cond.L) //time.Sleep(time.Second) cond.L.Unlock() // 多次wait 如果不释放锁,别的抢不到。 }() } time.Sleep(time.Second) // 在发信号之前,要有等待的cond cond.Signal() // 只唤醒 1个 等待c的goroutine cond.Signal() // 只唤醒 1个 等待c的goroutine time.Sleep(time.Second * 2) on := sync.Once{} for i := 0; i < 2; i++ { go func() { fmt.Println("====") on.Do(func() { fmt.Println("-------") }) }() } time.Sleep(time.Second) var syncMap sync.Map //并发操作一个map的时候,内置的map不是并发安全啊 syncMap.Store("key1", "value1") fmt.Println(syncMap.Load("key")) syncMap.LoadOrStore("key2", "value2") syncMap.Delete("key") syncMap.Range(func(key, value interface{}) bool { fmt.Println(key, value) return true // 是否继续进行遍历 }) }