go 互斥锁与读写锁

互斥锁

互斥锁控制下的多个写操作之间、多个读操作之间是互斥的,并且写操作与读操作之间也是互斥的。

互斥锁适用于读写不确定场景,即读写次数没有明显的区别,并且只允许只有一个读或者写的场景,所以该锁叶叫做全局锁,也就是完全互斥。

互斥锁是传统的并发程序对共享资源进行访问控制的主要手段。它由标准库代码包sync中的Mutex结构体类型代表。sync.Mutex类型(确切地说,是*sync.Mutex类型)只有两个公开方法――Lock和Unlock。顾名思义,前者被用于锁定当前的互斥量,而后者则被用来对当前的互斥量进行解锁。

使用方法

var mutex sync.Mutex

func write() { 
mutex.Lock() //加互斥锁
defer mutex.Unlock() //解互斥锁
// 省略若干条语句 
}

使用建议

  • 互斥锁的成对的锁定和解锁应该成对出现(虽然互斥锁可以被直接的在多个Goroutine之间共享)。
  • 把互斥锁作为某一个结构体类型中的字段,以便在该类型的多个方法中使用它。
  • 我们还应该使代表互斥锁的变量的访问权限尽量的低。这样才能尽量避免它在不相关的流程中被误用,从而导致程序不正确的行为。
  • 习惯使用defer,defer语句保证了在该函数被执行结束之前互斥锁mutex一定会被解锁。



读写锁

读写锁即是针对于读写操作的互斥锁。它与普通的互斥锁最大的不同就是,它可以分别针对读操作和写操作进行锁定和解锁操作。

也就是说,读写锁控制下的多个写操作之间都是互斥的,并且写操作与读操作之间也都是互斥的。但是,多个读操作之间却不存在互斥关系。

使用方法

var mutex sync.RWMutex

func write() { 
mutex.RLock() //加读写锁
defer mutex.RUnlock() //解读写锁
// 省略若干条语句 
}