OS | 读写锁【摘】

读写锁是用来解决读者写者问题的,读操作可以共享,写操作是排他的,读可以有多个在读,写只有唯一个在写,同时写的时候不允许读。

互斥锁与读写锁的区别:

当访问临界区资源时(访问的含义包括所有的操作:读和写),需要上互斥锁;

当对数据(互斥锁中的临界区资源)进行读取时,需要上读取锁,当对数据进行写入时,需要上写入锁。

读写锁的优点:

对于读数据比修改数据频繁的应用,用读写锁代替互斥锁可以提高效率。因为使用互斥锁时,即使是读出数据(相当于操作临界区资源)都要上互斥锁,而采用读写锁,则可以在任一时刻允许多个读出者存在,提高了更高的并发度,同时在某个写入者修改数据期间保护该数据,以免任何其它读出者或写入者的干扰。

读者-写者问题和生产者-消费者问题不同的是,后者的每个线程都要修改缓冲区的内容,所以不得不使用互斥锁来保证数据一致性,而前者有些线程是只读的,多个只读线程同时访问并不会出现数据不一致的情况,所以在实现上不必为每个线程都加一个互斥锁,而是让多个读线程可以同时访问,只有写进程的访问是互斥的。

这一篇博文写的很详细:http://ouonline.net/pthread-notes-3

写者优先的思考参考了:http://blog.csdn.net/yaozhiyi/article/details/7563869

读者优先:第一次读的时候获取锁,最后一次读的时候释放锁;这样只要有读操作,就不能写;

写者优先:

1. 对于写者:只要有写操作,就会尝试着去获取读锁,这样接下来的读就不能继续了,这样的尝试只需要一次,当没有写操作时就应该释放读锁。

2. 对于读者:只要有读操作,那么就尝试着去获取写锁,这样接下来的写也就不能继续,但是读者还是可以读;读操作会和写操作竞争读锁,这里确保了只有一个读操作和写操作竞争读锁;


关于写者优先,我的思路如下:

a. 需要写写互斥,所以需要下面的结构:

1 //写者
2 lock(&writeLock);
3 write();
4 unlock(&writeLock);

b. 需要读写互斥,所以:

 1 //写者;并且只需要第一个写请求去获取读锁
 2 lock(&writeCountLock);
 3 writeCount++;
 4 if (writeCount == 1) lock(&readLock);
 5 unlock(&writeCountLock);
 6 
 7 lock(&writeLock);
 8 write();
 9 unlock(&writeLock);
10 
11 unlock(&readLock);
12 
13 lock(&writeCountLock);
14 writeCount--;
15 if (writeCount == 0) unlock(&readLock);
16 unlock(&writeCountLock);
1 //读者
2 lock(&readLock);
3 read();
4 unlock(&readLock);

c. 在读的时候,应该获取写锁,这样才能保证读的时候不写;但这是没有写操作时的处理;

 1 //读者
 2 lock(&readCountLock);
 3 readCount++;
 4 if (readCount == 1) lock(&writeLock);
 5 unlock(&readCountLock);
 6 
 7 read();
 8 
 9 lock(&readCountLock);
10 readCount--;
11 if (readCount == 0) unlock(&writeLock);
12 unlock(&readCountLock);

d. 如果此时有一个新的写操作,为了让它能够竞争到读锁,那么要让新来的read锁住,很明显就是在read()的前面要锁住,而且是和读锁相关,并且是限定了竞争时读的个数为1.所以加在Line2-5的外围。

// 读者
lock(&readLock);
lock(&readCountLock);
readCount++;
if (readCount == 1) lock(&writeLock);
unlock(&readCountLock);
unlock(&readLock);

read();

lock(&readCountLock);
readCount--;
if (readCount == 0) unlock(&writeLock);
unlock(&readCountLock);

这样是能保证,没有新的读的时候,永远只是竞争一个读锁来更新readCount,然后read()这里是可以并行的。

原文地址:https://www.cnblogs.com/linyx/p/3969566.html