线程同步——读写锁

参考学习资料:进程线程互斥与同步

1. 读写锁

1.1 读写锁变量

pthread_rwlock_t lock; (一个变量是一把锁)

读写锁使用时,一个变量是一把锁。

1.2 读写锁类型

  1. 读锁:对内存做读操作;
  2. 写锁:对内存做写操作。

1.3 读写锁的特性

  1. 线程A加读锁成功,又来了三个线程,做读操作,可以加锁成功。(读共享 - 并行处理
  2. 线程A加写锁成功,又来了三个线程,做读操作,三个线程阻塞。(写独占 - 串行处理
  3. 线程A加读锁成功,又来了B线程加写锁阻塞,又来了C线程加读锁阻塞。(读写不能同时进行,写的优先级高

1.4 读写锁场景练习

(1) 线程A加写锁成功,线程B请求读锁

线程B阻塞

(2) 线程A持有读锁,线程B请求写锁

线程B阻塞

(3) 线程A持有读锁,线程B请求读锁

线程B加锁成功(有关为什么A加了读锁之后,B还要加读锁?因为A的读锁在A任务处理完毕之后就释放了,但是此时B可能没有执行完,所以每个线程都要有自己独立的锁,互不影响)

(4) 线程A持有读锁,线程B请求写锁,然后线程C请求读锁

B阻塞,C阻塞(写的优先级高);

因此A解锁之后,B线程加写锁成功,C继续阻塞;

B解锁成功,C加读锁。

(5) 线程A持有写锁,线程B请求读锁,然后线程C请求写锁

线程B阻塞,线程C阻塞;

A解锁,C加写锁成功 (写锁优先级高);

C解锁,B加读锁成功。

1.5 读写锁的适用场景

互斥锁:读写串行工作;

读写锁:读 - 并行;写 - 串行。

程序中读操作大于写操作的时候,加读写锁更合适。

1.6 主要操作函数

(1) 初始化读写锁

pthread_rwlock_init(
	pthread_rwlock_t* restrict rwlock,//读写锁变量
	const pthread_rwlockattr* restrict attr//参数默认为NULL
);

(2)销毁读写锁

pthread_rwlock_destroy(pthread_rwlock_t* rwlock);

(3)加读锁

pthread_rwlock_rdlock(pthread_rwlock_t *rwlock)

如果之前对这把锁加的是写操作,线程阻塞。

(4)尝试加读锁

pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);

尝试加锁成功,返回0;失败返回错误号。

(5)加写锁

pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);

上一次加写锁,还未解锁的时候,阻塞;

上一次加读锁,还未解锁的时候,阻塞。

(6)尝试加写锁

pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);

加锁成功,返回0;否则返回错误号。

(7)解锁

pthread_rwlock_unlock(pthread_rwlock_t *rwlock);

2. 代码示例(C语言)

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pthread.h>
//定义全局变量
int number=0; 

//创建读写锁
pthread_rwlock_t lock; 

void* write_func(void* arg){
	//x循环写 
	while(1){
		//加写锁
		pthread_rwlock_wrlock(&lock); 
		number++;
		printf("== write: %lu, %d\n",pthread_self(),number);
		pthread_rwlock_unlock(&lock); //解除写锁 
		usleep(500);
	}
	return NULL;
}

void* read_func(void* arg){
	//x循环读 
	while(1){
		//加读锁 
		pthread_rwlock_rdlock(&lock); 
		printf("== read: %lu, %d\n",pthread_self(),number);
		pthread_rwlock_unlock(&lock); //解除读锁 
		usleep(500);
	}
	
	return NULL;
}

int main(void){
	pthread_t p[8];
	pthread_rwlock_init(&lock,NULL);
	//创建三个写线程
	int i=0;
	for(;i<3;i++ ){
		pthread_create(&p[i],NULL,write_func,NULL);
	} 
	//创建5个读线程
	for(;i<8;i++ ){
		pthread_create(&p[i],NULL,read_func,NULL);
	} 
	//阻塞回收线程的资源
	for(i=0;i<8;i++){
		pthread_join(p[i],NULL);
	} 
	//释放读写锁资源 
	pthread_rwlock_destroy(&lock);
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值