回想一下上面介绍的互斥量,它只有两个状态,要么是加锁状态,要么是不加锁。假如现在一个线程 a 只是想读一个共享变量 i ,因为不确定是否会有线程去写他,所以我们还是要对它进行加锁。但是这时候又一个线程 b 试图读共享变量i ,于是发现被锁住,那么b不得不等到a释放了锁后才能获得锁并读取 i 的值,
但是两个读取操作即使是几乎同时发生也并不会像写操作那样造成竞争,应为他们不修改变量的值。所以我们期望如果是 多个线程试图读取共享变量的 值的话,那么他们应该可以立刻获取而不需要等待前一个线程释放因为读而加的锁。
读写锁解决了上面的问题。他提供了比互斥量跟好的并行性。因为以读模式加锁后当又有多个线程仅仅是试图再以读模式加锁然时,并不会造成这些线程阻塞在等待锁的释放上。
注意我们只是说 读写锁提高了 更高的并行性,也就是说允许多个线程几乎同一时间读取一个共享变量,而互斥锁不行。但是不是 使用读写锁就会比互斥量快呢?我们下面会做一些测试
读写锁的特点是:
当读写锁是写加锁时,在这个锁被解锁之前,所有试图对这个锁加锁的线程都会被阻塞。
当读写锁是读加锁时,在这个锁被解锁之前,所有试图以读模式对他进行加锁的线程都可以得到访问权,但是如果线程以写模式对此锁加锁时会造成阻塞,直到所有线程释放读锁
这里有一个问题,如果一个线程现 A 获得一把读锁,现在来了一个线程B请求写锁,那么它就要等到线程A释放读锁,但是如果在A释放之前又一个线程获得了读锁(读锁可以多次获得),
并且在改线程释放读锁之前又一个线程请求到了读锁,假设后续一直有读锁请求成功,那么请求写锁的进程B就不得不一直阻塞等待所有读锁的释放。所以相关的实现一般让当一个读写锁处于读模式锁住时,此时来了另一个线程的写模式加锁请求,那么读写锁通常会阻塞随后的读模式锁请求,这样可以避免锁被读模式长期占用,而写模式请求一直得不到满足。