Linux多线程的同步------读写锁

本文详细介绍了Linux多线程同步中的读写锁机制,对比了读写锁与互斥锁的区别。读写锁允许多个读操作并发进行,而写操作互斥。通过代码示例展示了未使用和使用读写锁时的运行结果,强调了读写锁在多线程环境中的重要性,并探讨了锁的优先级问题。
摘要由CSDN通过智能技术生成

前面介绍过Linux多线程同步的另外两个方法------互斥锁和信号量

Linux多线程的同步-----信号量和互斥锁_神厨小福贵!的博客-CSDN博客

下面来看一下读写锁:

        读写锁和互斥锁都带有一个锁,那么他们有什么区别呢?

读写锁互斥锁
多个读操作可以同时进行一次只有一个线程拥有互斥锁,其他线程只有等待
写操作之间必须互斥
读写操作之间也是互斥的,且写操作的应优先于读操作(写操作执行的时候,其他函数都在阻塞)

上面说到了读写锁和互斥锁的区别,相信大家对读写锁已经有了一定的理解,下面来看读写锁所用到的函数以及头文件:
头文件:#include <pthread.h> 

读写锁初始化函数:

int pthread_rwlock_init(pthread_rwlock_t *rwlock, pthread_rwlockattr_t *attr); 

第一个参数是读写锁指针,第二个参数是读写锁的属性的指针(一般置为NULL)----下面附上官方手册

 读锁:int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock); 

写锁:int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock); 

解锁:int pthread_rwlock_unlock(pthread_rwlock_t *rwlock); 

销毁锁:int pthread_rwlock_destroy(pthread_rwlock_t *rwlock); 

函数里面的参数都是所创建的读写锁的指针

下面来看一个代码示例:下面代码是没有加读写锁🔓的代码

#include <stdio.h>
#include <stdlib.h> 
#include <unistd.h>
#include <string.h>
#include <pthread.h>
   
pthread_rwlock_t rwlock;//读写锁的创建
 
void * read_fun1(void * arg)   //读子线程的函数
{
    while(1)
    {
        printf("read1 start \n");
        sleep(1);
        printf("read2 end \n");
    }
} 
void * read_fun2(void * arg)
{
    while(1)
    {
        printf("read2 start \n");
        sleep(1);
        printf("read2 end \n");
    }
}
  
void * write_fun(void * arg)
{
    while(1)
    {
        printf("write start \n");
        sleep(1);
        printf("write end  \n");
    }
}

int main()
{
    pthread_rwlock_init(&rwlock,NULL);
    pthread_t idr1,idr2; //创建两个读的线程
    pthread_t idw;  //创建一个写的线程

    pthread_create(&idr1,NULL,read_fun1,NULL);
    pthread_create(&idr2,NULL,read_fun2,NULL);
    pthread_create(&idw,NULL,write_fun,NULL);

    pthread_join(idr1,NULL);
    pthread_join(idr2,NULL);
    pthread_join(idw,NULL);

    pthread_rwlock_destroy(&rwlock);
    exit(0);
}
~     

上面代码没有加读写锁,我们来运行结果:

 运行结果可看出,在读操作进行的同时,写操作也在进行着,那么我们再来看一下加了读写锁之后的运行结果

来看加了读写锁之后的代码:

#include <stdio.h>
#include <stdlib.h> 
#include <unistd.h>
#include <string.h>
#include <pthread.h>
   
pthread_rwlock_t rwlock;//读写锁的创建
 
void * read_fun1(void * arg)   //读子线程的函数
{
    while(1)
    {
        pthread_rwlock_rdlock(&rwlock);   //对读操作枷锁
        printf("read1 start \n");
        sleep(1);
        printf("read2 end \n");
        pthread_rwlock_unlock(&rwlock);   //读完进行解锁
    }
} 
void * read_fun2(void * arg)
{
    while(1)
    {
        pthread_rwlock_rdlock(&rwlock);   //对读操作枷锁
        printf("read2 start \n");
        sleep(1);
        printf("read2 end \n");
        pthread_rwlock_unlock(&rwlock);   //读完进行解锁
    }
}
  
void * write_fun(void * arg)
{
    while(1)
    {
        pthread_rwlock_wrlock(&rwlock);   //对写操作枷锁
        printf("write start \n");
        sleep(1);
        printf("write end  \n");
         pthread_rwlock_unlock(&rwlock);   //写完进行解锁
    }
}

int main()
{
    pthread_rwlock_init(&rwlock,NULL);
    pthread_t idr1,idr2; //创建两个读的线程
    pthread_t idw;  //创建一个写的线程

    pthread_create(&idr1,NULL,read_fun1,NULL);
    pthread_create(&idr2,NULL,read_fun2,NULL);
    pthread_create(&idw,NULL,write_fun,NULL);

    pthread_join(idr1,NULL);
    pthread_join(idr2,NULL);
    pthread_join(idw,NULL);

    pthread_rwlock_destroy(&rwlock);
    exit(0);
}
~     

加了锁之后再来运行   看结果:

 看了结果发现,诶,怎么还是不对啊,怎么没有写操作呢?

在我上面的代码中,是读操作的线程创建函数先于写操作的线程创建函数,然后刚开始就是读拿锁,又因为读操作是可以同时拿锁的,所以两个读操作同时拿锁,中间可能会有间隔 ,但是这个间隔时间之中是另外一个读操作在拿锁,所以写操作就一直拿不到锁,但是你只要给每次解锁之后加个睡眠一秒钟的函数,就会改善这种情况

#include <stdio.h>
#include <stdlib.h> 
#include <unistd.h>
#include <string.h>
#include <pthread.h>
   
pthread_rwlock_t rwlock;//读写锁的创建
 
void * read_fun1(void * arg)   //读子线程的函数
{
    while(1)
    {
        pthread_rwlock_rdlock(&rwlock);   //对读操作枷锁
        printf("read1 start \n");
        sleep(1);
        printf("read2 end \n");
        pthread_rwlock_unlock(&rwlock);   //读完进行解锁
        sleep(1);
    }
} 
void * read_fun2(void * arg)
{
    while(1)
    {
        pthread_rwlock_rdlock(&rwlock);   //对读操作枷锁
        printf("read2 start \n");
        sleep(1);
        printf("read2 end \n");
        pthread_rwlock_unlock(&rwlock);   //读完进行解锁
        sleep(1);
    }
}
  
void * write_fun(void * arg)
{
    while(1)
    {
        pthread_rwlock_wrlock(&rwlock);   //对写操作枷锁
        printf("write start \n");
        sleep(1);
        printf("write end  \n");
        pthread_rwlock_unlock(&rwlock);   //写完进行解锁
        sleep(1);
    }
}

int main()
{
    pthread_rwlock_init(&rwlock,NULL);
    pthread_t idr1,idr2; //创建两个读的线程
    pthread_t idw;  //创建一个写的线程

    pthread_create(&idr1,NULL,read_fun1,NULL);
    pthread_create(&idr2,NULL,read_fun2,NULL);
    pthread_create(&idw,NULL,write_fun,NULL);

    pthread_join(idr1,NULL);
    pthread_join(idr2,NULL);
    pthread_join(idw,NULL);

    pthread_rwlock_destroy(&rwlock);
    exit(0);
}

加上睡眠函数之后的运行结果:

 就可以了,这是因为在读完数据之后,间隔那一秒钟,读操作空闲不拿锁的时候,那个写操作就可以拿到锁子,但是这玩意说到底的优先级是什么,别人做过实验,结果是写操作优先:

读写锁的一个奇怪表现 - 付哲 - 博客园

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值