多个gotoutine同时操作一个资源,这个资源叫做临界区
在并发条件下,如果多个goroutine在没有相互同步的情况下,访问某个共享的资源,会处于相互竞争的状态,导致并发中的资源/数据竞争问题。如下面的程序,2个goroutine 对count各执行10w 次加一操作,打印出的最终结果很有可能不是20w
package mainimport ("fmt""sync")var (wg sync.WaitGroupcount int)func incCount() {defer wg.Done()for i := 0; i < 100000; i++ {count ++}}func main() {wg.Add(2)go incCount()go incCount()wg.Wait()fmt.Println(count)}
执行 go run —race main.go 会告诉你有数据竞争DATA RACE的问题
go run -race main.go==================WARNING: DATA RACERead at 0x0000005ef648 by goroutine 7:==================181708Found 1 data race(s)exit status 66
互斥锁同时有且只有一个线程进入临界区,其他的线程则在等待锁,当互斥锁释放后,等待锁的线程才可以获取锁进入临界区,当多个线程同时等待同一个锁,唤醒的策略是随机的
Mutex是互斥锁
// Lock 用于锁住 m,如果 m 已经被加锁,则 Lock 将被阻塞,直到 m 被解锁。func (m *Mutex) Lock()// Unlock 用于解锁 m,如果 m 未加锁,则该操作会引发 panic。func (m *Mutex) Unlock()
eg:
package mainimport ("fmt""sync")var (wg sync.WaitGroupcount int32mu sync.Mutex)func incCount() {defer wg.Done()for i := 0; i < 100000; i++ {mu.Lock()count++mu.Unlock()}}func main() {wg.Add(2)go incCount()go incCount()wg.Wait()fmt.Println(count)}
参考
https://draveness.me/golang/docs/part3-runtime/ch06-concurrency/golang-sync-primitives/
http://xiaorui.cc/archives/5951
https://cloud.tencent.com/developer/article/1596863
