linux读写锁

2023-05-16

这里写目录标题

  • 读写锁的认识
  • 读写锁的相关函数
  • 练习

读写锁的认识

(1)读写锁是一把锁
(2)读写锁的类型: pthread_rwlock_t lock 又分“读锁”(对内存进行读操作)和“写锁”(对内存进行写操作)
(3)读写锁的特性:
1)读共享-并行处理:例如,线程 A 加读锁成功,有来个 3 个线程,作读操作,也可加锁成功。
2)写独占-串行处理:例如,线程 A 加写锁成功,有来个 3 个线程,作读操作,3 个线程阻塞。
3) 读写不能同时进行,写的优先级高:例如,线程A加读锁成功,又来了B线程加写锁阻塞,又来了C线程加读锁阻塞
(4)读写锁的场景练习:
1)线程 A 加写锁成功,线程 B 请求读锁 :B 读阻塞。
2)线程 A 加读锁成功,线程 B 请求写锁 :B 写阻塞。
3)线程 A 加读锁成功,线程 B 请求读锁 :线程 B 加读锁成功。
4)线程 A 加读锁成功,然后线程 B 请求写锁,然后线程 C 请求读锁 :B 写阻塞,C 读阻塞;
A 解锁 :B 加写锁成功,C 继续读阻塞 ;
B 解锁 :C 加读锁成功。
5)线程 A 加读写成功,然后线程 B 请求读锁,然后线程 C 请求写锁 :B 读阻塞,C 写阻塞;
A 解锁 :C 加写锁成功,B 继续读阻塞;
C 解锁 :B 加读锁成功。
(5)读写锁与互斥锁的区别
互斥锁 : 读写串行 。
读写锁 : 读并行,写串行。
读写锁更关注“读并行”,如果关注串行,那直接用互斥锁好了,所以读写锁更适用于读操作多的场景,通过其并行的特性,可以提高效率。

读写锁的相关函数

初始化读写锁

pthread_rwlock_init(pthread_rwlock_t* restrict rwlock,const pthread_rwlockattr_t* restrict attr );

销毁读写锁

pthread_rwlock_destroy(pthread_rwlock_t* rwlock):

加读锁

pthread_rwlock_rdlock(pthread_rwlock_t* rdlock);

阻塞:之前对这把锁加的是写锁的操作
尝试加读锁

pthread_rwlock_tryrdlock(pthread_rwlock_t* rwlock);

加锁成功:返回0
失败:返回错误号
加写锁

pthread_rwlock_wrlock(pthread_rwlock_t* rwlock);

阻塞:上一次加写锁还没解锁
阻塞:上一次加读锁还没解锁
尝试加写锁

pthread_rwlock_trywrlock(pthread_rwlock_t* rwlock);

解锁

pthread_rwlock_unlock(pthread_rwlock_t* rwlock)

练习

三个线程不定时写同一个全局变量,五个线程不定时期读同一全局资源
先不加锁:

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

int number=0;
pthread_rwlock_t rwlock;
void *write_pthread(void * arg)
{
        while(1)
        {
                //pthread_rwlock_wrlock(&rwlock);
                number++;
                printf("write_pthread id:%ld, number is %d\n",pthread_self(),number);
                usleep(500);
                //pthread_rwlock_unlock(&rwlock);
        }
}
void *read_pthread(void * arg)
{
        while(1)
        {
                //pthread_rwlock_wrlock(&rwlock);
                printf("read_pthread id: %ld,number is %d\n",pthread_self(),number);
                usleep(500);
                //pthread_rwlock_unlock(&rwlock);
        }
}

int main()
{
        pthread_t p[8];
        pthread_rwlock_init(&rwlock,NULL);
        for(int i=0;i<3;i++)
        {
                pthread_create(&p[i],NULL,write_pthread,NULL);
        }
        for(int i=3;i<8;i++)
        {
                pthread_create(&p[i],NULL,read_pthread,NULL);
        }
        for(int j=0;j<8;j++)
        {
                pthread_join(p[j],NULL);
        }
        return 0;
}

截取结果片段:
请添加图片描述
发现读的number值有时会小于写的number值,这因为没加读写锁时,读和写线程都是并发执行,会引发混乱。

加读写锁:

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

int number=0;
pthread_rwlock_t rwlock;
void *write_pthread(void * arg)
{
        while(1)
        {       //加写锁
                pthread_rwlock_wrlock(&rwlock);
                number++;
                printf("write_pthread id:%ld, number is %d\n",pthread_self(),number);
                pthread_rwlock_unlock(&rwlock);
                //解锁
                sleep(1);
        }
}
void *read_pthread(void * arg)
{
        while(1)
        {       //加读锁
                pthread_rwlock_wrlock(&rwlock);
                printf("read_pthread id: %ld,number is %d\n",pthread_self(),number);
                pthread_rwlock_unlock(&rwlock);
                //解锁
               sleep(1);
        }
}

int main()
{
        pthread_t p[8];
        pthread_rwlock_init(&rwlock,NULL);
        for(int i=0;i<3;i++)
        {
                pthread_create(&p[i],NULL,write_pthread,NULL);
        }
        for(int i=3;i<8;i++)
        {
                pthread_create(&p[i],NULL,read_pthread,NULL);
                 }
        for(int j=0;j<8;j++)
        {
                pthread_join(p[j],NULL);
        }
        return 0;
}

执行结果:
请添加图片描述
可以看到加了读写锁以后,读是并行的,写串行的,number的顺序是由小到大,不会发生混乱。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

linux读写锁 的相关文章

  • 使用 cmake 和 opencv 对符号“gzclose”的未定义引用[关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 我尝试构建该项目 doppia https bitbucket org rodrigob doppia 但发生链接错误 我想这是一
  • 打印堆栈指针的值

    如何在 Linux Debian 和 Ubuntu 中用 C 打印堆栈指针的当前值 我尝试谷歌但没有找到结果 一个技巧是简单地将本地地址作为指针打印出来 但它不可移植 甚至无法保证有效 void print stack pointer vo
  • “排序文件名 | uniq”不适用于大文件

    我可以从小文本文件中删除重复条目 但不能从大文本文件中删除重复条目 我有一个 4MB 的文件 文件的开头如下所示 aa aah aahed aahed aahing aahing aahs aahs aal aalii aalii aali
  • PHP exec - 检查是否启用或禁用

    有没有办法检查 php 脚本是否exec 在服务器上启用还是禁用 这将检查该功能是否确实有效 权限 权利等 if exec echo EXEC EXEC echo exec works
  • 使用Linux虚拟鼠标驱动

    我正在尝试实施一个虚拟鼠标驱动程序根据基本 Linux 设备驱动程序书 有一个用户空间应用程序 它生成坐标以及内核模块 See 虚拟鼠标驱动程序和用户空间应用程序代码 http www embeddedlinux org cn Essent
  • 如何获取uinput创建的设备的名称(路径)

    我已经成功设置了一个小程序来创建uinput questions tagged uinput我计划使用它来自动测试接收键盘输入事件的应用程序 我已关注both http thiemonge org getting started with
  • 为所有图像添加前缀(递归)

    我有一个包含 5000 多张图像的文件夹 全部带有 JPG 扩展名 我想要做的就是递归地向所有图像添加 thumb 前缀 我发现了一个类似的问题 重命名文件和目录 添加前缀 https stackoverflow com questions
  • 用于列出用户和组的 Python 脚本

    我正在尝试编写一个脚本 在自己的行上输出每个用户及其组 如下所示 user1 group1 user2 group1 user3 group2 user10 group6 etc 我正在为此用 python 编写一个脚本 但想知道如何做到这
  • 验证 BASH 脚本时出现问题 [已关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 我在尝试验证 bash 脚本时出现代码 lint 错误 bin bash if eq 0 then printf No argum
  • 无法使用Linux服务启动Archiva 2.1.0

    我正在尝试在 Linux 上启动最近发布的 Apache Archiva v2 1 0 独立版 出于测试目的 该 zip 已解压缩在 opt archiva 2 0 文档说 http archiva apache org docs 2 1
  • 有没有比使用 backtrace() 更便宜的方法来查找调用堆栈的深度?

    我的日志记录代码使用的返回值回溯 http linux die net man 3 backtrace确定当前堆栈深度 出于漂亮的打印目的 但我可以从分析中看到这是一个相当昂贵的调用 我不认为有更便宜的方法吗 请注意 我不关心帧地址 只关心
  • 如何在 Linux 上调用 Python 中的内联机器代码?

    我正在尝试从 Linux 上的纯 Python 代码调用内联机器代码 为此 我将代码嵌入到字节文字中 code b x55 x89 xe5 x5d xc3 然后打电话mprotect http www kernel org doc man
  • 使用 Shell 脚本提供密码

    我已将客户端和服务器设置为无密码登录 就像无密码登录一样 通过将服务器的 RSA 密钥复制到所有客户端的 root ssh id rsa pub 来实现 但这是我手动完成的 我喜欢使用 shell 脚本自动执行此过程 并通过脚本向计算机提供
  • 每个进程是否都存在内核堆栈?

    每个用户空间进程是否都存在一个内核堆栈和一个用户空间堆栈 如果两个堆栈都存在 那么每个用户空间进程应该有 2 个堆栈指针 对吗 在 Linux 中 每个任务 用户空间或内核线程 都有一个 8kb 或 4kb 的内核堆栈 具体取决于内核配置
  • 在 Unix 中,我可以在目录中运行“make”而无需先 cd 到该目录吗?

    在 Unix 中 我可以运行make在没有的目录中cd首先进入该目录 make C path to dir
  • Linux 源代码中的哪个位置会识别特定的 USB 设备?

    我有一个特定的 USB 设备 我想检查其 Linux 驱动程序源代码 我的理解是 USB 驱动程序执行的第一步是注册自己能够处理具有特定供应商 ID 和产品 ID 的设备 就我而言 供应商 ID 是0BDA产品 ID 是8187 有了这些信
  • 套接字发送并发保证

    如果我在两个进程 或两个线程 之间共享一个套接字 并且在这两个进程中我尝试发送一条阻塞的大消息 大于下划线协议缓冲区 是否可以保证这两个消息将按顺序发送 或者消息可以在内核内部交错吗 我主要对 TCP over IP 行为感兴趣 但了解它是
  • MYSQL插入GB大小的巨大SQL文件

    我正在尝试创建 Wikipedia DB 副本 大约 50GB 但在处理最大的 SQL 文件时遇到问题 我使用 linux split 实用程序将 GB 大小的文件拆分为 300 MB 的块 例如 split d l 50 enwiki 2
  • C中的内存使用问题

    请帮忙 操作系统 Linux 其中 sleep 1000 中 此时 top 显示Linux任务 给我写了7 7 MEM使用 valgrind 未发现内存泄漏 我明白 写得正确 所有 malloc 结果都是 NULL 但是为什么这次 睡眠 我
  • 从命名管道读取

    我必须实现一个 打印服务器 我有 1 个客户端文件和 1 个服务器文件 include

随机推荐

  • 自制无人机(一)

    2022 1 30第一篇博客 xff0c 记录一下 过年放假最后几天没事干 xff0c 打算做个无人机玩玩 看了些开源的项目 xff0c 为了省钱 xff0c PCB板直接当机架 xff0c 白嫖嘉立创10 10的板 xff0c 要求不高
  • 【C/C++】STL简介

    简单介绍一下STL STL是什么 xff1f STL standard template libaray 标准模板库 xff1a 是C 43 43 标准库的重要组成部分 xff0c 不仅是一个可复用的组件库 xff0c 而且是一个包罗数据结
  • Nvidia Jetson Xavier 上使用CAN

    为了利于回忆 xff0c 将自己查询到的资料在这里记录一下 资料一 xff1a 20条消息 NVIDIA Xavier CAN weifengdq的专栏 CSDN博客 资料二 xff1a 英文版Enabling CAN on Nvidia
  • 数据传输中的 奇校验、偶校验

    1 在数字设备中 xff0c 数据的传输是大量的 xff0c 且传输的数据都是由若干位二进制代码 0 和 1 组合而成的 系统内部或外部干扰等原因 xff0c 可能是数据信息在传输过程中产生错误 xff0c 例如在发送端 xff0c 待发送
  • freertos任务创建失败,使得任务句柄为空,导致任务被调度就会进入断言死循环

    项目场景 xff1a 添加openlog的部署 前几天帮队友的代码找bug xff0c 在原有的控制代码之上 xff0c 添加了两个新的freertos任务部署了openlog模块 xff1b 原来已经存在一些任务 xff0c 其中按照代码
  • 关于Qt的概述

    知识在于积累 古语有言 不积跬步无以至千里 不积小流无以成江海 虽然总是在学习 但是一些知识平时不用 过后就印象不深刻了 所以 记录些回过头来看看也很有帮助 什么是QT Qt是一个针对桌面 嵌入式 移动设备的一个跨平台的应用程序开发框架 支
  • 2022数学建模国赛B题:无人机定位(国二分享)

    无人机集群在遂行编队飞行时 xff0c 为避免外界干扰 xff0c 应尽可能保持电磁静默 xff0c 少向外发射电 磁波信号 为保持编队队形 xff0c 拟采用纯方位无源定位的方法调整无人机的位置 xff0c 即由编队中某 几架无人机发射信
  • stm32串口DMA方式向上位机连续发送数据

    目录 一 认识DMA1 DMA框图2 什么是DMA xff1f 3 DMA传输方式4 DMA传输参数5 DMA数据传输的四个要素6 DMA的应用场景 二 串口DMA方式向上位机发送数据1 实验要求2 通过STMCube配置项目 1 设置RC
  • 结构体中的对齐数到底是什么

    我们如何计算结构体的大小 xff0c 是不是把所有元素的大小都加起来 xff0c 当然不是 xff0c 要不然这样也太简单了 xff0c 那我们到底如何来计算结构体的大小呢 xff1f 例如一下的代码 struct s1 char c1 i
  • MPU6050温度计算公式

    Tem为16位数据 Tem 43 12412 340 61 Tem 340 43 36 5 Tem每340对应1摄氏度 12412代表0摄氏度
  • 立体匹配中的Rank变换原理

    立体匹配分为代价计算 代价聚合 视差计算 视差优化这几个主要步骤 xff0c 其中的重点 难点是前两步 之前一直搞不懂Rank变换是怎样能通过变换降低噪声对匹配结果的影响 xff1f Rank变换是一种基于数理统计的非参量变换方法 xff0
  • 立体匹配之Rank变换c++代码实现

    include lt iostream gt include lt unistd h gt include lt opencv2 opencv hpp gt include lt opencv2 imgproc hpp gt include
  • linux系统的进程占用cpu信息监控C++

    linux系统下的进程以及cpu信息都实时存储在 proc stat文件里 xff0c 只需要提取对应的时间信息就可以获取cpu的信息 xff0c 进程的信息则存储在 proc pid stat proc stat文件包含了所有CPU活动的
  • 用java套接字socket实现两台电脑间的通信

    实现效果 xff1a 一方发送简单的文字消息 发送 接收复杂的图片 音频 文档等 相互之间实现自由通信 java对网络编程的支持 前提条件 xff1a 两台电脑在一个局域网内 xff0c 比如连接了同一个路由器 将一台电脑作为服务端 xff
  • 【STM32标准库】【自制库】硬件串口通信和标准输入输出函数的重定向

    文章目录 硬件串口通信电气连接初始化思路1 初始化GPIO2 GPIO复用选择3 开启时钟4 初始化结构体USART BaudRateUSART WordLengthUSART StopBitsUSART ParityUSART ModeU
  • 什么是A*(Astar)算法?(简单叙述)

    目录 简介 A 算法的原理与思想 A 算法处理与搜索 实例 xff08 引用见文末 xff09 简介 A 算法 xff08 启发式搜索 xff09 的首要条件是在静态路网中 xff0c 相对于广度优先遍历 xff08 BFS xff09 求
  • Qt的安装和配置

    1 Windows安装Qt5及VisualStudio配置 安装 VS nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp 安装Visual Studio过程忽略 但是需要注意 切记勾选 Visual C 选项
  • 基于STM32F103系列芯片使用IIC协议来写oled(硬件IIC)

    提示 xff1a 文章写完后 xff0c 目录可以自动生成 xff0c 如何生成可参考右边的帮助文档 文章目录 前言一 协议是什么IIC xff1f 二 相关代码 1 main c2 oled c总结 前言 提示 xff1a 这里可以添加本
  • linux里 read函数用法

    Read 函数 从打开的 fd 设备或文件中读取 count 个字节到 buf 中 ssize tread int fd void buf size tcount fd 文件描述符 buf 读入数据的首地址 count 读入数据的个数 返回
  • linux读写锁

    这里写目录标题 读写锁的认识读写锁的相关函数练习 读写锁的认识 xff08 1 xff09 读写锁是一把锁 xff08 2 xff09 读写锁的类型 xff1a pthread rwlock t lock 又分 读锁 xff08 对内存进行