02Linux下C语言锁的学习之Linux下的读写锁

2023-11-20

02Linux下C语言锁的学习之Linux下的读写锁

概述:
下面的锁的意思均是代表读写锁。
读写锁的特性:

  • 1)若一把锁被一个线程以读方式锁住,当其它线程以读方式上锁的话,那么可以上锁成功。

  • 2)若一把锁被一个线程以写方式锁住,当其它线程以读或者写方式上锁的话,都会被阻塞。

  • 要注意的是:多个线程同时请求锁时,请求读方式的线程会被放在请求写方式的线程后面;若不是同时请求上锁,读方式先请求的则先等已经上锁的线程处理后再处理(当然如果该线程以读方式上锁可以同时进行),即使后面再有写请求也要等其完成才能上锁。 这里的同时和不是同时很重要。

  • 实际上上面的意思可以总结为:

读时共享,写时阻塞(独占),写锁优先级高,注意同时与非同时字眼,注意目前以何种方式上锁。//记住这五句话就可以完全吃透读写锁的各个线程的执行顺序了。具体可以看下面的场景分析。

有点类似fork创建子进程时继承父进程的全局变量。

1 与Linux下的读写锁相关的函数介绍
1)pthread_rwlock_init函数

int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);
/*
	功能:初始化一把锁。
	参1:读写锁。
	参2:读写锁属性,通常使用默认属性,传NULL即可。
*/

2)pthread_rwlock_destroy函数

int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
/*
	功能:销毁一把锁。
	参1:读写锁。
*/

3)pthread_rwlock_rdlock函数

int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
/*	
	功能:以只读方式锁住读写锁。
	参1:读写锁。
*/

4)pthread_rwlock_wrlock函数

int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
/*
	功能:以读写方式上锁,简称叫以写方式上锁。
	参1:读写锁。
*/

5)pthread_rwlock_unlock函数

int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
/*
	功能:解锁。
	参1:读写锁。
*/

6)pthread_rwlock_tryrdlock函数

int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
/*
	功能:以读方式尝试请求读写锁(非阻塞请求读锁)。
	参1:读写锁。
*/

7)pthread_rwlock_trywrlock函数

int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
/*
	功能:以写方式尝试请求读写锁(非阻塞请求写锁)
	参1:读写锁。
*/

2 读写锁的场景分析
1)场景一:均是读请求。
当下面4个线程请求读写锁时,不管是否是同时,都能成功上锁访问数据。
在这里插入图片描述

2)场景2:T1,T2线程同时上锁,T3,T4在后面请求。
由于T1,T2是同时请求上锁,但写请求优先级高,所以T2先上锁,其它线程阻塞。T2线程处理完后T1,T3,T4均能上锁,上锁的顺序看CPU先处理哪个请求,不需要考虑顺序。
在这里插入图片描述

3)场景3:T1,T2在以读方式上锁时,T3,T4以写方式请求。
因为T1,T2已经上锁,所以T3,T4会阻塞等待,即使你是以写方式请求。
写请求优先级高是针对于没有上锁且是同时请求的情况下。

  • 注意:当一把锁被写方式锁住时,读方式请求先到,然后再以写方式请求,由于锁被锁住,所以这种也认为是同时,写方式请求将被放在读方式请求之前。
    当一把锁被读方式锁住时不需要考虑,因为再以读方式先请求的话会共享,写方式再请求因读方式请求已经共享,所以实际剩下自己,已经无对比可言。
    在这里插入图片描述

4)场景4:T1先以读方式加锁成功,后面三个线程同时请求。
这里再提醒一下:若T1先加锁成功,在操作期间,T2,T3,T4即使按不同顺序(除了T2放在前并且CPU开始处理该请求,否则即使T2先请求但是还在队列时T3请求来了那么顺序发生改变,T2即使在最前同样不可以共享),也是认为是同时(看场景3的解释),因为T1还在操作期间嘛。

当T1在操作期间,由于是同时请求并且写优先级高,那么T3一定会被排在T2,T4线程之后,所以T3不可能共享,必须等到T2,T4处理完后才能访问。
在这里插入图片描述

3 读写锁代码例子
代码很简单,创建了3个写线程,5个读线程。共享资源为int型全局变量。


/* 3个线程不定时 "写" 全局资源,5个线程不定时 "读" 同一全局资源 */

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

int counter;                          //全局资源
pthread_rwlock_t rwlock;

//写线程的回调函数
void *th_write(void *arg)
{
    int t;
    int i = (int)arg;

    while (1) {
		//写线程期间,独占
        pthread_rwlock_wrlock(&rwlock);
		t = counter;
        usleep(1000);//模拟业务,让读线程获取CPU,但是读线程因为锁被锁住而阻塞
        printf("=======write %d: %lu: counter=%d ++counter=%d\n", i, pthread_self(), t, ++counter);
        pthread_rwlock_unlock(&rwlock);
		
        usleep(5000);//让其它线程获取锁,防止本线程回到while又重新上锁,导致其它线程很少机会获取到锁
    }
	
    return NULL;
}

//读线程的回调函数
void *th_read(void *arg)
{
	//区别线程几的因子
    int i = (int)arg;

    while (1) {
		//读线程期间,读时共享
        pthread_rwlock_rdlock(&rwlock);
        printf("----------------------------read %d: %lu: %d\n", i, pthread_self(), counter);
        pthread_rwlock_unlock(&rwlock);

        usleep(900);//让其它线程获取锁,防止本线程回到while又重新上锁,导致其它线程很少机会获取到锁
    }
	
    return NULL;
}

//这里为了简单没做错误分析
int main(void)
{
    int i;
    pthread_t tid[8];//线程id

    pthread_rwlock_init(&rwlock, NULL);
	
	//创建3个写线程
    for (i = 0; i < 3; i++)
        pthread_create(&tid[i], NULL, th_write, (void *)i);
	
	//创建5个读线程
    for (i = 0; i < 5; i++)
        pthread_create(&tid[i+3], NULL, th_read, (void *)i);
	
	//回收子线程资源
    for (i = 0; i < 8; i++)
        pthread_join(tid[i], NULL);
	
	//释放读写琐
    pthread_rwlock_destroy(&rwlock);            

    return 0;
}

上面程序会不断打印count被写和读共享时的值。
截图部分分析结果:
1)下图看到,问:write 0:4150012746那行在写期间,黑色部分的上锁请求可能同时进行吗?
答:不可能,如果同时请求,那么根据写请求优先,write 2那行必定在前面的read前面,所以write 2是在那10个读线程之后请求的。
在这里插入图片描述

2)问:蓝色框里面的请求有可能是一起来的吗?
答:就是一起同时来的,然后根据优先级写请求放在前面。因为根据write 2上面是读可以知道,如果不是一起来的话,write 1下面的读请求先于write 2先来,那么是可以共享的,应该在write 2前共享。
在这里插入图片描述

4 总结读写锁
由于读写锁在实际应用很少用,并且麻烦,所以不建议大家使用,并且一般互斥锁就够Linux下的C程序员使用了。这里只是让大家有这个概念。要搞明白读写锁如何排序线程的请求,记住概述的那五句话即可,都是按照那五句话进行排序请求。

读写锁完结。

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

02Linux下C语言锁的学习之Linux下的读写锁 的相关文章

  • [SUCTF 2019]EasyWeb

    SUCTF 2019 EasyWeb 打开环境是一段代码 其中if preg match x00 0 9A Za z x7F i hhh 这个判断是难点 它的绕过可以参考这篇文章https www h3399 cn 201909 72364

随机推荐

  • 接口自动化测试学习指南(2023版)

    一 为什么要学习接口自动化测试 1 1 了解接口自动化测试的重要性 提高效率与速度 持续集成与持续交付 准确性与一致性 更广泛的覆盖范围 持久回归测试 节省成本与资源 早期发现问题 提升团队信心 可重复与可维护性 支持多平台与多环境 1 2
  • python离线语音转文字

    1 安装SpeechRecognition第三方库 pip install SpeechRecognition 2 安装pocketsphinx第三方库 安装时 可能会报错error command swig exe failed No s
  • 多益网络笔试

    一笔 2017 05 19 基本上考的是写概率题和智力题 没来得及整理就忘得差不多 最后一个题是个推理题 二笔 2017 05 25 单选 C 的基础知识 二叉树结点计算 填空 类的操作 结构体 联合体的大小计算 简答 1 如何理解虚析构
  • Excel VBA获取最后一行列

    测试excel文件 VBA代码 Function getLastRow Debug Print End xlUp Sheets 1 A65536 End xlUp Row Debug Print usedRange ActiveSheet
  • Linux操作文档——FTP文件传输服务

    文章目录 一 基本概念 1 FTP连接及传输模式 2 用户列表文件ftpusers和user list 二 基于系统用户的FTP服务 1 匿名访问的FTP服务 2 用户验证的FTP服务 三 基于虚拟用户的FTP服务 1 建立虚拟用户的账号数
  • 网站页面导入css,图片等文件的相对路径和绝对路径问题

    相对路径 表示上一级目录开始 表示当前同级目录开始 相对 肯定是个参考对象 很多人可能会认为这个参考对象就是导入css或图片等的页面 但其实对于网站访问而言 这个对象是参考你所访问的url地址的 因为最近在写thinkphp 相对的话对于t
  • Angular6以ng serve方式启动时指定环境方法及关联知识点

    一 踩坑 1 问题来源 如何自定义环境并在启动时指定环境 2 解决方案 使用configuration参数启动项目 如ng serve configuration local or ng serve c local启动名为local的环境
  • 【C语言】C语言零碎知识点

    需要云服务器等云产品来学习Linux的同学可以移步 gt 腾讯云 lt gt 阿里云 lt gt 华为云 lt 官网 轻量型云服务器低至112元 年 新用户首次下单享超低折扣 目录 1 sizeof和strlen 2 函数形参 很重要 2
  • Android Studio中的Java控制台中出现乱码问题?

    今天在用Android studio 中敲代码时发现控制台出不了汉字 一打汉字全是乱码的 在此特供解决方案 在Java的工程目录build gradle下添加如下代码 1 新版gradle tasks withType JavaCompil
  • “AI+大数据+智能机器人”新型政企运营服务模式

    在建设智慧城市的大背景下 人工智能技术在智慧政务方面已有多个重点建设场景 即通过 互联网 政务服务 构建智慧型政企 利用 AI 大数据 智能机器人 的模式构建智慧政务服务平台 不断探索新型政企运营服务模式 提升服务水平和效率 实现由 传统政
  • Fatal error: Uncaught --> Smarty: unable to write file

    多是文件权限问题 chmod R 777 该文件夹下所有文件
  • Nacos配置与本地配置优先级

    概述 由Apollo配置中心与本地配置优先级 引出的一个问题 号称时下最强的注册中心和配置中心 表现如何 调研 直接上代码 本地配置文件application dev yml 新增配置 test aaa 接口层的测试方法 Value tes
  • windows 10 环境下 的 flutter 环境配置教程及 问题解决办法

    最近开始接触flutter 小白一枚 记录一下最近安装flutter的过程 因为自己电脑已经安装了Android Studio 和 git 工具 因此直接从安装flutter说起 1 去官网下载flutter 安装包 https flutt
  • ElasticSearch教程

    第一章 ElasticSearch入门篇 第一节 ElasticSearch概述 1 1ElasticSearch是一个基于Lucene的搜索服务器 它提供了一个分布式多用户能力的全文搜索引擎 基于RESTfulweb接口 ElasticS
  • Signature verification failed on downloaded file

    下载文件上签名验证失败 原因 为了验证文件下载过程中是否出现丢包或其他原因导致文件出现损坏 会对比前后的hash码 不一致就会报错 Hash码 基于文件的内容通过算法得到的数值 与文件的名称无关 根据文件内容计算
  • STM32F103C8移植uCOSIII(HAL库)

    少年 一 随笔 二 uCOSIII源码 三 项目导入文件整理 四 导入文件和增加头函数路径 五 代码改动 六 参考资料 一 随笔 移植一个嵌入式系统用了一天时间 只能说不愧是我 在不了解的情况下还是少一些自己的操作 自己挖坑埋自己 记录一下
  • JavaEE项目实战(OA系统)之十九_流程审批之二

    JavaEE项目实战 OA系统 之十九 流程审批之二 这部分的程序界面原型如下 1 请假页面 员工如需请假 在登录系统后 点击请假功能 填写各项数据后 提交审批 也可以暂时不提交 将内容保存为草稿 以后可以加入功能 查看我的请假 和 草稿箱
  • 【Linux】Linux中jar包的压缩和解压缩

    1 概述 问题 在生产环境 有时会有需要修改jar中url的需求 目前我遇到的 此时 unzip tar命令都失去了用武之地 解决办法 假如文件 是file jar ls l xx xxx xx flink lang jar xx xxx
  • 端口访问被拒绝的解决方案

    端口访问被拒绝的解决方案 ps 本人亲测 阿里云2核4G5M的服务器性价比很高 新用户一块多一天 老用户三块多一天 最高可以买三年 感兴趣的可以戳一下 阿里云折扣服务器 问题描述 比如在本机telent到192 168 8 170 主机的9
  • 02Linux下C语言锁的学习之Linux下的读写锁

    02Linux下C语言锁的学习之Linux下的读写锁 概述 下面的锁的意思均是代表读写锁 读写锁的特性 1 若一把锁被一个线程以读方式锁住 当其它线程以读方式上锁的话 那么可以上锁成功 2 若一把锁被一个线程以写方式锁住 当其它线程以读或者