首先通过下面的例子了解下什么是并发安全:

猜猜结果是什么? 40000? 有可能,但不一定:

每次输出都不一样,就像随机数?

num并不一定等于40000,这是由于两个goroutine在读写num变量时存在数据竞争的原因,所以最终结果不一定与期待值一致


怎么解决数据竞争呢?

可以这样,当A goroutine读写变量时,锁住变量的读写权限,使得其他goroutine不能去读写即可

sync包里的两把锁就是为了解决并发安全而存在的,下面一一介绍


sync.Mutex

mutex是mutual exclusion的缩写,是互斥的意思,一般称其为互斥锁:

重点:

  1. 未初始化的sync.Mutex就已经是一个未上锁的互斥锁(零值即可用)

  2. sync.Mutex和sync.WaitGroup一样,一旦开始使用,不能够再次复制

每次读写num变量时,加锁,读写完后,解锁:

这样每次执行的结果都是一致的:

perfect!

还有一个要注意的点是,尽可能的去使用defer sync.Unlock,否则有可能出现panic时,没法执行Unlock

所以再改动下代码:

好习惯而已,num++一般不会panic


sync.RWMutex

rwmutex是reader/writer mutual exclusion的缩写,它表示一个读写互斥锁

读写包含两个操作,一个是读取,一个是修改。

sync.Mutex会将读写一起锁住,而sync.RWMutex允许只锁写操作或只锁读操作,而且一个goroutine的读操作不会影响另一个goroutine的读操作

所以边读边写的情况下,RWMutex比Mutex更高效


写锁操作方法:

读锁操作方法:

下面是例子: