Linux多线程编程(四)-----读写锁

概述

读写锁类似于互斥锁(互斥量),不过读写锁允许更高的并行性,主要体现在读者方面。这种锁有利于读的机会多,写的机会少的共享数据。它可分为以下两种情况:

  • 写者竞争到锁资源。在写者加锁,正在写的情况下,所有试图竞争这个锁的读者写者线程都会被阻塞。
  • 读者竞争到锁资源。在读写加锁,正在读的情况下,为了体现并行性,当有新读者试图读取并且申请加锁的时候,将被允许。也就是说,一块共享数据可以同时被多个读者读取。但当有写者试图写时,将被阻塞。直到所有的读者线程释放锁为止。

但是,通常在读者占用锁资源的情况下(可能有一个读者,可能有多个读者),当一个写者请求锁资源,系统通常会阻塞随后的读者请求。这样做可以保证被读的资源充足。并且防止读者一直占用锁,而写者长时间得不到满足。
注意,共享数据这个概念是很重要的,读写锁也可以理解为就是用来保护这块共享数据的。

操作函数

与互斥锁相同,读写锁也有自己的类型:pthread_rwlock_t。

初始化方式

在创建互斥锁的时候有两种方式,①:定义一个全局变量pthread_rwlock_t。②利用malloc进行动态分配。切记不可定义成局部变量,读写锁是要被多个线程访问的,如果读写锁是被定义在一个线程内部的局部变量,当出了作用域被另一个线程访问时,这个锁就变成了无效的,还有可能引起无法预料的后果。

-利用宏PTNREAD_RWLOCK_INITIALIZER
定义一个全局变量,直接利用宏PTNREAD_RWLOCK_INITIALIZER进行初始化。

pthread_rwlock\_t lock = PTNREAD_RWLOCK_INITIALIZER;

- 调用函数pthread_rwlock_init
定义一个局部的或者全局的读写锁,调用函数进行初始化。

#include <pthread.h>
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,
              const pthread_rwlockattr_t *restrict attr);

init函数有两个参数,第一个参数rwlock即为我们定义的读写锁,我们一般讲第二个参数attr指针设为null,代表互斥锁有默认属性。

摧毁

在利用完读写锁释放空间之前,需要调用pthread_rwlock_destroy做一些清理工作,释放锁资源 。init负责分配初始化锁资源,那必须就有destroy负责回收。如果还没有调用detroy进行释放锁资源,内存空间就被释放了,那么分配给这个锁的资源就会丢失。

#include<pthread.h>
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);

加锁解锁

读写锁针对读者写者不同,设计了两种加锁函数。而解锁只有一种。

#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,失败返回错误码。所以在每次申请锁资源时,都应检测是否申请成功。

除了上面两个函数外,还有以下两个尝试加锁函数。当申请不到锁资源时,线程就会被阻塞,而有些线程不希望这样。所以就可以调用尝试加锁,成功返回0,失败时直接返回错误EBUSY。

#include<pthread.h>
int pthread_rwlock_tyrrdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);

代码实例

#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>

pthread_rwlock_t lock; //定义读写锁
int data = 0;//定义共享数


//读者线程
void* thread_read(void* arg)
{
    while(1)
    {
      sleep(1);
      //读者申请锁,成功返回0,
      if(pthread_rwlock_wrlock(&lock) == 0)
      {
          printf("Reader read a number: %d\n",data);
            pthread_rwlock_unlock(&lock);//解锁
      }
      else
      {
            printf("@\n@\n");
      }
    }
}

//写者线程
void* thread_write(void* arg)
{
    while(1)
    {
        usleep(50000);
        //写者申请锁,成功返回0.
        if(pthread_rwlock_wrlock(&lock) == 0)
        {
            data++;
            printf("Writer write a number: %d\n",data);
            pthread_rwlock_unlock(&lock);//解锁
        }
        else
        {
            printf("@\n@\n");
        }

{

    pthread_rwlock_init(&lock,NULL);//init函数初始化锁,分配锁资源

    pthread_t reader;
    pthread_t writer;
    //创建读者线程
    pthread_create(&reader,NULL,thread_read,NULL);
    //创建写者线程
    pthread_create(&writer,NULL,thread_write,NULL);

    pthread_join(reader,NULL);
    pthread_join(writer,NULL);

    pthread_rwlock_destroy(&lock);//释放锁资源

    return 0;
}
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值