1.基本概念
读写锁:是计算机程序的并发控制的一种同步机制,也称“共享-互斥锁”、多读者-单写者锁。读操作可并发重入,写操作是互斥的。
主要适用的场景是:读多写少的业务场景。这种场景下如果每次读写都使用互斥锁那么整个效率就会变得很低。因为只是读的话并不需要互斥锁来锁住数据,只有写操作的时候需要互斥锁,而读写结合的时候,也是需要加锁的,不然的话会导致读的数据不一定是期望的。
对于RWMutex的规则如下:
1、可以随便读,多个goroutine同时读。
2、写的时候,不能读也不能写。
主要有下面四个API构成,读锁RLock,RUnlock,写锁Lock,Unlock。
这没有任何非凡的地方。和mutex相关的所有事情都是通过sync.Mutex类型的两个方法sync.Lock()和sync.Unlock()函数来完成的,前者用于获取sync.Mutex锁,后者用于释放sync.Mutex锁。sync.Mutex一旦被锁住,其它的Lock()操作就无法再获取它的锁,只有通过Unlock()释放锁之后才能通过Lock()继续获取锁。
也就是说,已有的锁会导致其它申请Lock()操作的goroutine被阻塞,且只有在Unlock()的时候才会解除阻塞。
另外需要注意,sync.Mutex不区分读写锁,只有Lock()与Lock()之间才会导致阻塞的情况,如果在一个地方Lock(),在另一个地方不Lock()而是直接修改或访问共享数据,这对于sync.Mutex类型来说是允许的,因为mutex不会和goroutine进行关联。如果想要区分读、写锁,可以使用sync.RWMutex类型,见后文。
在Lock()和Unlock()之间的代码段称为资源的临界区(critical section),在这一区间内的代码是严格被Lock()保护的,是线程安全的,任何一个时间点都只能有一个goroutine执行这段区间的代码。
1)多个读锁可以同时操作 .
2)写锁一旦加锁,不管是读操作还是写操作都不能被执行。
3)读锁加锁了之后,只要读锁还没有解锁,写操作是不能被执行的。