目录
1. 读写锁介绍
读写锁的类型可以分为读锁和写锁,以读方式给数据加锁—读锁。以写方式给数据加锁—写锁。但是读写锁是一把锁,每个线程只可以带一个锁类型。
特性:(举例说明)
1. 线程A加读锁成功,又来了三个线程,做读操作,三个线程再次加锁成功。
———结论:读时共享,并行处理
2.线程A加写锁成功,又来了三个线程,做读操作,三个线程再次加锁失败。
———结论:写时独占
3.线程A加锁成功,又来了线程B加写锁阻塞,又来了C线程加读锁阻塞。
———结论:(1)读写不能同时进行,(2)写的优先级高
举例:线程A持写锁,B请求读锁,C请求写锁。
B,C线程先阻塞;A解锁后,C加写锁成功,B继续阻塞;C解锁后,B加锁成功。
2. 读写锁的操作函数
读写锁的过程和互斥锁类似,不作详细介绍,由特性可知,相较于互斥锁而言,当读线程多的时候,可以提高访问效率。适合使用在读操作的次数远大于写操作的时候,读写锁的相关函数如下:
主要操作函数:
1. 创建读写锁
pthread_rwlock_t rwlock;
2. 初始化读写锁
int pthread_rwlock_init(
pthread_rwlock_t *restrict rwlock,
const pthread_rwlockattr_t *restrict attr
);
3. 加读锁
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
阻塞:之前对这边锁加写锁操作时阻塞
4. 尝试加读锁,try
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
5. 加写锁
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
阻塞:上一次加读锁和写锁任意一种,没有解锁都会阻塞。
6. 尝试加写锁
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
7. 解锁
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
8.销毁
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
以上函数都是成功返回0,失败返回错误号。
3. 读写锁示例代码
/* 3个线程不定时 "写" 全局资源,5个线程不定时 "读" 同一全局资源 */
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <pthread.h>
// 全局变量
int number;
pthread_rwlock_t rwlock;
void* write_func(void* arg)
{
while(1)
{
//加写锁
pthread_rwlock_wrlock(&rwlock);
number++;
printf("+++ write number: %d\n", number);
//解锁
pthread_rwlock_unlock(&rwlock);
usleep(1000);
}
return NULL;
}
void* read_func(void* arg)
{
while(1)
{
pthread_rwlock_rdlock(&rwlock);
printf("--- read number: %d\n", number);
pthread_rwlock_unlock(&rwlock);
usleep(500);
}
return NULL;
}
int main(int argc, const char* argv[])
{
pthread_t thid[8];
pthread_rwlock_init(&rwlock, NULL);
// 创建3个写线程
for(int i=0; i<3; ++i)
{
pthread_create(&thid[i], NULL, write_func, NULL);
}
//创建5个读线程
for(int i=3; i<8; ++i)
{
pthread_create(&thid[i], NULL, read_func, NULL);
}
// 回收子线程的pcb
for(int i=0; i<8; ++i)
{
pthread_join(thid[i], NULL);
}
//释放读写锁资源
pthread_rwlock_destroy(&rwlock);
return 0;
}
运行结果:一直循环下去。