读写锁比mutex有更高的适用性,能够多个线程同一时候占用读模式的读写锁。可是仅仅能一个线程占用写模式的读写锁。
1. 当读写锁是写加锁状态时,在这个锁被解锁之前,全部试图对这个锁加锁的线程都会被堵塞;
2. 当读写锁在读加锁状态时,全部试图以读模式对它进行加锁的线程都能够得到訪问权。可是以写模式对它进行枷锁的线程将堵塞;
3. 当读写锁在读模式锁状态时,假设有另外线程试图以写模式加锁,读写锁一般会堵塞随后的读模式锁请求,这样能够避免读模式锁长期占用。而等待的写模式锁请求长期堵塞;
这样的锁适用对数据结构进行读的次数比写的次数多的情况下。由于能够进行读锁共享。
API接口说明:
1) 初始化和销毁
#include <pthread.h>
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
成功则返回0, 出错则返回错误编号.
2) 读加锁和写加锁
获取锁的两个函数是堵塞操作
#include <pthread.h>
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
成功则返回0, 出错则返回错误编号.
3) 非堵塞获得读锁和写锁
非堵塞的获取锁操作, 假设能够获取则返回0, 否则返回错误的EBUSY.
#include <pthread.h>
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
成功则返回0, 出错则返回错误编号.
实例代码
/*************************************************************
* pthread_rwlock_test2.c:验证读写锁的默认顺序
* 假设在main函数中用pthread_rwlock_wrlock上锁。那么
* 假设全部线程都堵塞在写锁上的时候,优先处理的是被堵塞的写锁
* 然后才处理读出锁
* 假设在main函数中用pthread_rwlock_rdlock上锁。那么
* 假设有读者正在读的时候即使后面到来的写者比另外一些到来的读者更早
* 也是先处理完读者,才转而处理写者,这样会导致写饥饿
*
* 由此(运行结果)能够看出,LINUX平台默认的是读者优先。假设想要以写者优先
* 则须要做一些处理
**************************************************************/
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
pthread_rwlock_t rwlock;
void *readers(void *arg)
{
pthread_rwlock_rdlock(&rwlock);
printf("reader %d got the lock
", (int)arg);
pthread_rwlock_unlock(&rwlock);
//return NULL;
}
void *writers(void *arg)
{
pthread_rwlock_wrlock(&rwlock);
printf("writer %d got the lock
", (int)arg);
pthread_rwlock_unlock(&rwlock);
//return NULL;
}
int main(int argc, char **argv)
{
int retval, i;
pthread_t writer_id, reader_id;
pthread_attr_t attr;
int nreadercount = 1, nwritercount = 1;
if (argc != 2) {
fprintf(stderr, "usage, <%s threadcount>", argv[0]);
return -1;
}
retval = pthread_rwlock_init(&rwlock, NULL);
if (retval) {
fprintf(stderr, "init lock failed
");
return retval;
}
pthread_attr_init(&attr);
//pthread_attr_setdetachstate用来设置线程的分离状态
//也就是说一个线程怎么样终止自己,状态设置为PTHREAD_CREATE_DETACHED
//表示以分离状态启动线程
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
//分别在main函数中对读出者和写入者加锁。得到的处理结果是不一样的
pthread_rwlock_wrlock(&rwlock);
// pthread_rwlock_rdlock(&rwlock);
for (i = 0; i < atoi(argv[1]); i++) {
if (random() % 2) {
pthread_create(&reader_id, &attr, readers, (void *)nreadercount);
printf("create reader %d
", nreadercount++);
} else {
pthread_create(&writer_id, &attr, writers, (void *)nwritercount);
printf("create writer %d
", nwritercount++);
}
}
printf("main unlock
");
pthread_rwlock_unlock(&rwlock);
sleep(5);//sleep是为了等待另外的线程的运行
return 0;
}
參考: