读写锁
读写锁与互斥量类似。也是通过加锁的方式来实现线程之间的数据同步。互斥量的特点是 一次只有一个线程对其加锁。而对于度操作来说,即使有多个线程同时进行读操作是不会 产生冲突的。读写锁便利用了这个特性。它一共有三个状态:读模式下加锁状态,写模式 下加锁状态和不加锁状态。使用的规则如下:
- 当读写锁是写加锁状态时,在这个锁被解锁之前,所有试图对这个锁加锁的线程都会被阻塞。但是以读方式枷锁的线程是可以操作共享数据的。
- 当读写锁是读加锁状态时,所有试图以读模式对它进行加锁的线程都可以得到访问权限但是如果线程希望以写模式对此锁进行加锁,它必须阻塞直到所有的线程释放读锁。
读写锁非常适合对数据结构读的次数远大于写的情况。
接口函数
读写锁用 pthread_rwlock_t
数据类型表示。操作读写的函数与互斥量接口函数非常相似:
#include <pthread.h>
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,
const pthread_rwlockattr_t *restrict attr);
int pthread_rwlock_destory(pthread_rwlock_t *rwlock);
两者的返回值都是:若成功返回0;否则返回错误编号
读写锁使用之前需要使用 pthread_rwlock_init
函数进行初始化。attr
参数可以设置为 NULL 表示使用默认属性的读写锁。在使用完读写锁之后需要调用 pthread_rwlcok_destory
来释放读写锁的内存。
#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;否则返回错误编号
pthread_rwlock_rdlock
函数尝试以读模式加锁,pthread_rwlock_wrlock
函数尝试以写模式加锁。 在获得读写锁之后都可以通过 pthread_rwlock_unlock
函数解锁。
实例
#include <pthread.h> #include <stdio.h> int global = 0; pthread_rwlock_t rwlock = PTHREAD_MUTEX_INITIALIZER; void *fun1(void *arg) { int i = 0; for (; i < 50; i++) { pthread_rwlock_wrlock(&rwlock); global += 1; printf("pthread 1 write %d\n", global); sleep(1); pthread_rwlock_unlock(&rwlock); } pthread_exit((void*)1); } void *fun2(void *arg) { int i = 0; for (; i < 10; i++) { pthread_rwlock_rdlock(&rwlock); printf("pthread 2 read the global is %d\n", global); pthread_rwlock_unlock(&rwlock); } pthread_exit((void *)2); } int main() { pthread_t tid1, tid2; if (pthread_create(&tid1, NULL, fun1, NULL) != 0) return -1; if (pthread_create(&tid2, NULL, fun2, NULL) != 0) return -1; sleep(4); return 0; }
时间: 2024-10-06 00:27:34