转载请注明出处:https://blog.csdn.net/sublio/article/details/106503108
全系列目录:https://blog.csdn.net/sublio/article/details/106480267
锁 与 条件变量
目录
互斥锁
-
简单声明即可使用:
var mutex sync.Mutex mutex.Lock() mutex.Unlock()
-
(首次使用后?)不得复制(参考参考文献2),原因类似原子类型4(原子操作文档),解决方案:使用指针值。
-
应该配合defer使用及时解锁。
-
对已经锁定的锁进行锁定操作的goroutine会被阻塞,等待它被解锁。
-
在某一个锁被锁定的时候,可能会导致多个goroutine等待它解锁而被锁定,这些goroutine都有机会重新锁定这个锁,但只有一个goroutine会成功,其它goroutine继续阻塞等待下一次机会来临。
-
对未锁定的锁进行解锁会导致运行时恐慌,由于会导致一系列严重问题,Go1.8之后此类恐慌变得不可恢复。
读写锁
-
简单声明即可使用
var rwMutex sync.RWMutex //写锁定 rwMutex.Lock() rwMutex.Unlock() //读锁定 rwMutex.RLock() rwMutex.RUnlock()
-
(首次使用后?)不得复制(参考参考文献2),原因类似原子类型4(原子操作文档),解决方案:使用指针值。
-
读写之间互斥;写之间互斥;读之间不互斥。
-
有几个读锁定就应该有几个读解锁,应该配合defer使用及时解锁。
-
对未锁定的锁(无论是写锁还是读锁)进行解锁会导致运行时恐慌,会导致一个不可恢复的运行时恐慌。
-
rwMutex.RLocker()返回一个实现了sync.Locker接口类型的值。
-
互斥锁和读写锁实际上都是对接口类型sync.Locker的实现。
-
sync.Locker包含两个方法:Lock()和Unlock()。
-
rwMutex.RLocker()返回的是读写锁本身,但是调用rwMutex.RLocker()的Lock()和Unlock()实际上是在调用rwMutex的RLock()和RUnlock()。
-
意义在于,可以以相同的方式调用读锁和写锁,在一些场景下提供一些便利。
-
条件变量
-
无法通过简单声明直接使用。
//唯一参数sync.Locker,可以是互斥锁,也可以是读写锁,这里请注意读写锁的第5点。 //返回一个*sync.Cond类型 sync.NewCond(l Locker) //包含三个方法 Wait Signal Broadcast
-
(首次使用后?)不得复制(参考参考文献2),原因类似原子类型4(原子操作文档),解决方案:使用指针值。
-
Wait
-
自动对该条件变量关联的锁进行解锁,并使其所在的goroutine阻塞,等待被唤醒。
-
被唤醒时会立即尝试锁定该锁。
-
一定要在Wait被调用之前锁定相应的锁,否则该调用会引发一个不可恢复的运行时恐慌。
-
-
最后不要忘记解锁,因为Wait方法在返回之前会重新锁定其对应的锁。
-
Signal唤醒正在被Wait阻塞的一个goroutine,一般是任意唤醒队列中的一个(参考参考文献3)。
-
Broadcast唤醒所有正在被阻塞的goroutine。