读写锁
读写锁对于互斥锁而言,凡是涉及临界资源的访问一律加锁,这在并发读操作的场景下会大量浪费时间。要想提高访问效率,就必须要将对资源的读写操作加以区分:读操作可以多任务并发执行,只有写操作才进行恰当的互斥。Linux系统就提供了一种读写锁。
(1)读写锁的初始化
pthread_rwlock_t rwlock (= PTHREAD_RWLOCK_INITIALIZER); // 定义读写锁的变量并初始化,一定要全局变量,如果使用了下述初始化函数,括号内静态初始化就可以取消
pthread_rwlock_init(&rwlock, NULL); // const pthread_rwlockattr_t *restrict attr,第二个参数默认为NULL(2)读写锁的上锁和解锁
pthread_rwlock_rdlock(&rwlock); // 上读锁,并进行读操作
pthread_rwlock_wrlock(&rwlock); // 上写锁,并进行写操作,同一时间只有一把写锁,并与其他锁互斥
pthread_rwlock_unlock(&rwlock); // 解锁,读和写的解锁函数都相同
pthread_rwlock_destroy(&rwlock); // 不用了就销毁读写锁注意:读写锁适合多个线程对共享资源进行读操作和写操作,并且写操作没有读操作频繁的情况,另外要注意,如果多条线程对资源进行读取时,可以添加多把读操作锁。如果有一条线程准备对资源进行修改,则不应该有其他的线程再对资源进行读或者写,就相当于写操作和读操作是互斥的。如果已经有一条线程获取了写操作锁,那其他线程就无法获取写操作锁,就需要进行阻塞等待,所以就相当与写操作和写操作是互斥的。
(3)练习
设计一个程序,程序中有3个线程,主线程A创建一个文本,每隔5s获取一次系统时间并写入到该文本中,另外两个线程B和C分别从文本中读取当前的时间和日期,子线程B输出系统时间”hh:mm:ss”,子线程C输出系统日期”2024年05月31日”,要求使用读写锁实现互斥。 提示:主线程A获取写操作的锁,另外的线程分别获取读操作的锁。
#include <errno.h>
#include <stdio.h>
#include <pthread.h>
#include <time.h>
//定义全局变量
pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
FILE *time_fd;
//进程B
void * task_B(void *task_B)
{
char buf={0};
//设置分离属性
pthread_detach(pthread_self());
while(1)
{
//1.读锁
pthread_rwlock_rdlock(&rwlock);
//2.读取时间
time_fd = fopen("./time.txt", "r+");//打开文件
fread(buf,strlen(time_fd),1,time_fd);
printf("I am pthread B,time:%s", ctime(buf));
fclose(time_fd);
//3.解锁
pthread_rwlock_unlock(&rwlock);
sleep(2);
}
}
//进程C
void * task_C(void *task_B)
{
char buf={0};
//设置分离属性
pthread_detach(pthread_self());
while(1)
{
//1.读锁
pthread_rwlock_rdlock(&rwlock);
//2.读取时间
time_fd = fopen("./time.txt", "r+");//打开文件
fread(buf,strlen(time_fd),1,time_fd);
struct tm *p;
p = localtime(buf);
printf("%d年,%d月,%d日\r\n", (1900 + p->tm_year), (1 + p->tm_mon), p->tm_mday);
fclose(time_fd);
//3.解锁
pthread_rwlock_unlock(&rwlock);
sleep(2);
}
}
int main()
{
//1.初始化读写锁
pthread_rwlock_init(&rwlock,NULL);
//2.创建两个线程:线程B、线程C
pthread_t thread_C;
pthread_t thread_B;
pthread_create(thread_C,NULL,task_C,NULL);
pthread_create(thread_B,NULL,task_B,NULL);
//3.打开一个文本,如果不存在就创建
time_fd=fopen("./time.txt","wb+");
if(time_fd=NULL)
{
fprintf(stderr,"open time_log error,errno=%d,%s\n",errno,strerror(errno));
exit(-1);
}
//4.循环向time.txt文件中写入时间
while(1)
{
//1.写上锁
pthread_rwlock_wrlock(&rwlock);
//2.向time.txt文件中写入系统时间
time_t new;
time (&new);
fwrite(&new,sizeof(new),1,time_fd);
//3.解锁
pthread_rwlock_unlock(&rwlock);
//4.睡眠
sleep(5);
}
// 销毁读写锁
pthread_rwlock_destroy(&rwlock);
fclose(time_fd);
return 0;
}
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页:
[1]