读写锁比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\n", (int)arg);pthread_rwlock_unlock(&rwlock);//return NULL;
}
void *writers(void *arg)
{pthread_rwlock_wrlock(&rwlock);printf("writer %d got the lock\n", (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\n");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\n", nreadercount++);} else {pthread_create(&writer_id, &attr, writers, (void *)nwritercount);printf("create writer %d\n", nwritercount++);}}printf("main unlock\n");pthread_rwlock_unlock(&rwlock);sleep(5);//sleep是为了等待另外的线程的执行return 0;
}
参考:
- LINUX_IPC