【Linux C/C++ 线程同步 】Linux API 读写锁的编程使用

简介: 【Linux C/C++ 线程同步 】Linux API 读写锁的编程使用

读写锁介绍

读写锁比mutex有更高的适用性,可以多个线程同时占用读模式的读写锁,但是只能一个线程占用写模式的读写锁。

  • 当读写锁是写加锁状态时,在这个锁被解锁之前,所有试图对这个锁加锁的线程都会被阻塞;
  • 当读写锁在读加锁状态时,所有试图以读模式对它进行加锁的线程都可以得到访问权,但是以写模式对它进行枷锁的线程将阻塞;
  • 当读写锁在读模式锁状态时,如果有另外线程试图以写模式加锁,读写锁通常会阻塞随后的读模式锁请求,这样可以避免读模式锁长期占用,而等待的写模式锁请求长期阻塞;

读写锁使用场景

读写锁适用对数据结构进行读的次数比写的次数多的情况下,因为可以进行读锁共享。而互斥锁通常用于读写串行。

读写锁相关接口函数

  • 初始化读写锁
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);
//使用互斥变量之前必须初始化

参数:

rwlock:读写锁

attr:为NULL时,表示默认属性

返回值:

    若成功,返回0

    若失败,返回出错编号

  • 销毁读写锁
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
//在释放他们底层的内存之前必须摧毁

返回值:

    若成功,返回0

    若失败,返回出错编号

  • 读加锁和写加锁
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

    若失败,返回出错编号

  • 非阻塞获得读锁和写锁
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
 
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);

返回值:

    若成功,返回0

    若失败,返回出错编号

  • 带有超时的读写锁
int pthread_rwlock_timedwrlock(pthread_rwlock_t *restrict rwlock,const struct timespec *restrict abs_timeout);
 
int pthread_rwlock_timedrdlock(pthread_rwlock_t *restrict rwlock,const struct timespec *restrict abs_timeout);
//使应用程序获取读写锁时避免永久阻塞状态。

参数:

abs_timeout:指向timespec结构,指定线程应该停止阻塞的时间。

返回值:

    若成功,返回0

    若失败,返回出错编号

  • 初始化/销毁读写锁属性
int pthread_rwlockattr_init(pthread_rwlockattr_t *attr);
//将使用实现定义的所有属性的默认值初始化读写锁属性对象attr。
//如果指定已初始化的attr属性对象,则结果未定义。
 
int pthread_rwlockattr_destroy(pthread_rwlockattr_t *attr);
//销毁读写锁属性对象。

在读写锁属性对象用于初始化一个或多个读写锁之后,影响属性对象(包括破坏)的任何函数都不会影响任何先前初始化的读写锁。

返回值:

    若成功,返回0

    若失败,返回出错编号

  • 获取/设置读写锁属性对象的进程共享属性
int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *restrict attr, int *restrict pshared);
//从attr引用的初始化属性对象中获取进程共享属性的值。
//将attr的进程共享属性的值存储到由pshared参数引用的对象中。
 
int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *attr,int pshared);
//在attr引用的初始化属性对象中设置进程共享属性。

参数:

进程共享属性应设置为 PTHREAD_PROCESS_SHARED 以允许任何可访问读写锁定分配的内存的线程对读写锁操作,即使读写锁分配在内存中这是由多个进程共享的。

如果进程共享属性为 PTHREAD_PROCESS_PRIVATE 则读写锁只能在与初始化读写锁的线程相同的进程内创建的线程进行操作;

如果不同进程的线程尝试对这样的读写锁进行操作,则行为是未定义的。进程共享属性的默认值应为 PTHREAD_PROCESS_PRIVATE

返回值:

    成功 ,返回 0

    失败 ,返回 出错编号

使用示例

  • 读写锁简单使用代码段
//创建读写锁 
pthread_rwlock_t lock;
pthread_rwlock_init(&lock,NULL);
int data;
/** 写端线程  **/
     //加写锁
    pthread_rwlock_wrlock(&lock);
    data++;
    printf("==write:%lu,%d\n",pthread_self(),data);
    //解锁
    pthread_rwlock_unlock(&lock);
    sleep(1);
/** 读端线程     **/
    //加读锁
    pthread_rwlock_rdlock(&lock);
    printf("==read:%lu,%d\n",pthread_self(),data);
    pthread_rwlock_unlock(&lock);
    sleep(1);
//释放读写锁资源
pthread_rwlock_destroy(&lock);


目录
相关文章
|
安全 程序员 编译器
【实战经验】17个C++编程常见错误及其解决方案
想必不少程序员都有类似的经历:辛苦敲完项目代码,内心满是对作品品质的自信,然而当静态扫描工具登场时,却揭示出诸多隐藏的警告问题。为了让自己的编程之路更加顺畅,也为了持续精进技艺,我想借此机会汇总分享那些常被我们无意间忽视却又导致警告的编程小细节,以此作为对未来的自我警示和提升。
1341 93
|
10月前
|
存储 缓存 C++
C++ 容器全面剖析:掌握 STL 的奥秘,从入门到高效编程
C++ 标准模板库(STL)提供了一组功能强大的容器类,用于存储和操作数据集合。不同的容器具有独特的特性和应用场景,因此选择合适的容器对于程序的性能和代码的可读性至关重要。对于刚接触 C++ 的开发者来说,了解这些容器的基础知识以及它们的特点是迈向高效编程的重要一步。本文将详细介绍 C++ 常用的容器,包括序列容器(`std::vector`、`std::array`、`std::list`、`std::deque`)、关联容器(`std::set`、`std::map`)和无序容器(`std::unordered_set`、`std::unordered_map`),全面解析它们的特点、用法
C++ 容器全面剖析:掌握 STL 的奥秘,从入门到高效编程
|
存储 C++ UED
【实战指南】4步实现C++插件化编程,轻松实现功能定制与扩展
本文介绍了如何通过四步实现C++插件化编程,实现功能定制与扩展。主要内容包括引言、概述、需求分析、设计方案、详细设计、验证和总结。通过动态加载功能模块,实现软件的高度灵活性和可扩展性,支持快速定制和市场变化响应。具体步骤涉及配置文件构建、模块编译、动态库入口实现和主程序加载。验证部分展示了模块加载成功的日志和配置信息。总结中强调了插件化编程的优势及其在多个方面的应用。
1245 164
|
10月前
|
存储 机器学习/深度学习 编译器
【C++终极篇】C++11:编程新纪元的神秘力量揭秘
【C++终极篇】C++11:编程新纪元的神秘力量揭秘
|
10月前
|
存储 算法 C++
深入浅出 C++ STL:解锁高效编程的秘密武器
C++ 标准模板库(STL)是现代 C++ 的核心部分之一,为开发者提供了丰富的预定义数据结构和算法,极大地提升了编程效率和代码的可读性。理解和掌握 STL 对于 C++ 开发者来说至关重要。以下是对 STL 的详细介绍,涵盖其基础知识、发展历史、核心组件、重要性和学习方法。
|
10月前
|
存储 安全 算法
深入理解C++模板编程:从基础到进阶
在C++编程中,模板是实现泛型编程的关键工具。模板使得代码能够适用于不同的数据类型,极大地提升了代码复用性、灵活性和可维护性。本文将深入探讨模板编程的基础知识,包括函数模板和类模板的定义、使用、以及它们的实例化和匹配规则。
|
消息中间件 存储 安全
|
安全 程序员 编译器
【C++篇】继承之韵:解构编程奥义,领略面向对象的至高法则
【C++篇】继承之韵:解构编程奥义,领略面向对象的至高法则
203 11
|
存储 JavaScript 前端开发
Blazor 调用 Clipboard API 读写剪贴板数据
【10月更文挑战第14天】Blazor 是一个使用 .NET 和 C# 构建交互式 Web UI 的框架。由于浏览器安全策略,直接访问某些原生 API(如 Clipboard API)受限。通过 JavaScript 互操作性(JS Interop),可在 Blazor 中调用这些 API。首先在 HTML 定义 JavaScript 函数,再通过 `IJSRuntime` 调用。此外,需注意不同浏览器对 Clipboard API 的支持程度及用户隐私授权问题。
277 2
|
编译器 C语言 C++
C++入门6——模板(泛型编程、函数模板、类模板)
C++入门6——模板(泛型编程、函数模板、类模板)
219 0
C++入门6——模板(泛型编程、函数模板、类模板)