在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
参考: https://blog.csdn.net/li_101357/article/details/80286549(CSDN:sync包) https://zhuanlan.zhihu.com/p/138214620(知乎:sync包应用详解) https://studygolang.com/articles/3373(Mutex和rwmutex的区别) 在并发编程中同步原语也就是我们通常说的锁的主要作用是保证多个线程或者
sync.Mutex(互斥锁)func mutex() { type safeInt struct{ &sync.Mutex Num int } count:=&safeInt{} done:=make(chan bool) for i:=0;i<10000;i++{ go func(i int) { count.Lock() count.Num+=i count.Unlock() done<-true }(i) } for i:=0;i<10000;i++ { <-done } fmt.Println(count.Num) }
sync.RWMutex(读写锁)func rwMutex() { type safeInt struct{ &sync.RWMutex Num int } count:=&safeInt{} done:=make(chan bool) for i:=0;i<10000;i++{ go func(i int) { count.Lock()//写锁 count.Num+=i count.Unlock()//写锁 done<-true }(i) } for i:=0;i<10000;i++ { <-done //为了主协程等待 } fmt.Println(count.Num) } sync.WaitGroup(等待组)func waitGroup() { wg := &sync.WaitGroup{} for i := 0; i < 8; i++ { wg.Add(1) go func(i int) { // Do something fmt.Println(i) wg.Done() }(i) } wg.Wait() fmt.Println("done") } sync.Once(执行一次)func once() { once:=&sync.Once{} ch:=make(chan bool) for i:=0;i<10;i++ { go func() { once.Do(func() { fmt.Println("我自会执行一次") }) ch<-true }() } for i:=0;i<10;i++ { <-ch } } sync.Cond(条件变量)在 Wait 之前应当手动为 c.L 上锁,Wait 结束后手动解锁。为避免虚假唤醒,需要将 Wait 放到一个条件判断循环中。官方要求的写法如下: //控制方法 cond:=sync.NewCond(&mutex):生成一个cond,需要传入一个mutex,因为阻塞等待通知的操作以及通知解除阻塞的操作就是基于sync.Mutex来实现的。 cond.Wait():用于等待通知 cond.Signal():用于发送单个通知 cond.Broadcat():用于广播 //使用方式 cond.L.Lock() for !condition{ cond.Wait() } cond.L.UnLock() //满足条件后的后续逻辑 举例 func cond() { var locker sync.Mutex var cond = sync.NewCond(&locker) //等价于 var cond = &sync.Cond{L:&sync.Mutex{}} //locker.Lock() for i := 0; i < 10; i++ { go func(x int) { cond.L.Lock() // 获取锁 defer cond.L.Unlock() // 释放锁 cond.Wait() // 等待通知,阻塞当前 goroutine // 通知到来的时候, cond.Wait()就会结束阻塞, do something. 这里仅打印 fmt.Println(x) }(i) } time.Sleep(time.Second * 1) // 睡眠 1 秒,等待所有 goroutine 进入 Wait 阻塞状态 fmt.Println("Signal...") cond.Signal() // 1 秒后下发一个通知给已经获取锁的 goroutine time.Sleep(time.Second * 1) fmt.Println("Signal...") cond.Signal() // 1 秒后下发下一个通知给已经获取锁的 goroutine time.Sleep(time.Second * 1) cond.Broadcast() // 1 秒后下发广播给所有等待的goroutine fmt.Println("Broadcast...") time.Sleep(time.Second * 1) // 睡眠 1 秒,等待所有 goroutine 执行完毕 } func cond2() { sync.Map参考:https://blog.csdn.net/u010230794/article/details/82143179(csdn:sync.Map的使用和介绍) 利用传统的sync.RWMutex+Map实现并发安全的map//传统方式并发安全的map var rwmap = struct { sync.RWMutex m map[string]string }{m:make(map[string]string)} //写数据时 rwmap.Lock() rwmap.m["key"]="value123" rwmap.Unlock() //读数据时 rwmap.RLock() val:=rwmap.m["key"] rwmap.RUnlock() fmt.Println(val) 使用sync.Map实现func syncmap() { m := &sync.Map{} // 添加元素 m.Store(1, "one") m.Store(2, "two") // 获取元素1 value, contains := m.Load(1) if contains { fmt.Printf("%s\n", value.(string)) } // 返回已存value,否则把指定的键值存储到map中 value, loaded := m.LoadOrStore(3, "three") if !loaded { fmt.Printf("%s\n", value.(string)) } m.Delete(3) // 迭代所有元素 m.Range(func(key, value interface{}) bool { fmt.Printf("%d: %s\n", key.(int), value.(string)) return true }) }
|
请发表评论