读写锁与互斥量类似,不过读写锁允许更高的并行性。互斥量只有锁住和不加锁两种状态,且一次只有一个线程可以对其加锁。而读写锁有三种状态:读模式加锁状态,写模式加锁状态,不加锁状态。读写锁具有如下特点:
- 一次只有一个线程可以占有写模式的读写锁,但多个线程可以同时占有读模式的读写锁。
- 在写加锁状态下,在这个锁被解锁之前,所有试图对这个锁加锁的线程都会被阻塞。
- 在读加锁状态下,所有试图以读模式对它加锁的线程都可以得到访问权,但是希望以写模式加锁的线程会被阻塞,直到所有线程都释放它们的读锁。
- 当在读加锁状态下,有一个线程试图以写模式获取锁时,读写锁会阻塞后面的读模式锁请求。这样可以避免读模式锁长期占用,而写模式锁请求一直无法被满足。
读写锁适用于对数据读的次数远大于写的情况。在写加锁状态下,它所保护的数据可以被安全地修改;而在读加锁状态下,数据可以被多个线程并发地访问。
pthread对于读写锁提供了以下接口,它们的使用方式与互斥量基本相同
#include <pthread.h>
pthread_rwlock_t ; //读写锁的数据类型
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);
//初始化读写锁,参数attr传递属性,默认属性可使用null指针来传递
//默认属性的读写锁还可以通过常量 PTHREAD_RWLOCK_INITIALIZER 来初始化
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
//释放锁的内存前,做清理工作
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
//读模式加锁
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
//写模式加锁
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
//解锁
这里注意在各种实现中可能会对读模式下可以获取的读写锁的次数进行限制,所以需要检查pthread_rwlock_rdlock的返回值。