当前位置: 首页 > news >正文

Linux多线程同步机制(下)

文章目录

  • 前言
  • 一、读写锁
  • 二、条件变量
  • 总结

前言


一、读写锁

多线程同步机制中的读写锁(Read-Write Lock)是一种特殊的锁机制,用于控制对共享资源的读写访问。读写锁允许多个线程同时读取共享资源,但在写操作时需要独占访问。

读写锁的基本原则是:多个线程可以同时获取读锁,但只有一个线程可以获取写锁。当有线程持有写锁时,其他线程无法获取读锁或写锁,直到写操作完成并释放写锁。

读写锁有两种状态:读模式下加锁状态(读锁),写模式下加锁状态(写锁)。读写锁只有一把。

1. 读写锁的特性: 写独占,读共享。

  • 读写锁是 “ 写模式加锁 ” 时,解锁前,所有对该锁加锁的线程都会被阻塞。
  • 读写锁是 “ 读模式加锁 ” 时,如果线程以读模式 则对其加锁会成功;如果线程是以写模式加锁会阻塞。
  • 读写锁是 “ 读模式加锁 ” 时,既有试图以写模式加锁的线程,也有试图以读模式加锁的线程。那么读写锁会阻塞读模式请求。优先满足写模式加锁。读写锁并行阻塞,写锁优先级高。

2. 读写锁相关函数:

  • 初始化,pthread_rwlock_init
  • 获取读锁:使用pthread_rwlock_rdlock函数获取读锁。
  • 获取写锁:使用pthread_rwlock_wrlock函数获取写锁。
  • 释放锁:使用pthread_rwlock_unlock函数释放读锁或写锁。
  • 销毁读写锁:在不再需要时,使用pthread_rwlock_destroy函数销毁读写锁。

3. 示例代码:
下面代码设置一个写进程 和 三个读进程区访问共享资源。

(void*)i 将整数 i 转换为 void* 类型。在线程的函数中,需要将其转换回整数类型,以便使用它。可以使用 (int)arg 将 void* 转换回 int 类型。void* 是一种通用的泛型指针,可以在不关心具体类型的情况下进行转换和操作。

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>
#include <unistd.h>pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;		// 初始化读写锁int data = 1;void *write_thread (void *arg)
{while(1){pthread_rwlock_wrlock(&rwlock);data += 1;printf("write : data = %d\n",data);	pthread_rwlock_unlock(&rwlock);sleep(rand() %3);					// 随机休眠,让出 cpu资源}pthread_exit(NULL);
}void *read_thread (void *arg)
{int i = (int )arg;while(1){pthread_rwlock_rdlock(&rwlock);printf("read %d : data = %d\n",i, data);	pthread_rwlock_unlock(&rwlock);sleep(rand() %3);}pthread_exit(NULL);
}int main(void)
{pthread_t r_tid[5], w_tid;srand(time(NULL));// 创建多个读线程for (int i = 0; i < 3; i++) {pthread_create(&r_tid[i], NULL, read_thread, (void*)i);}pthread_create(&w_tid, NULL, write_thread, NULL);for(int j=0;j<3;j++)pthread_join(r_tid[j],NULL);pthread_join(w_tid,NULL);pthread_rwlock_destroy(&rwlock);return 0;
}

在这里插入图片描述

二、条件变量

在多线程编程中,条件变量是一种用于线程之间进行通信和同步的机制。条件变量允许一个线程等待特定的条件发生,并在条件满足时通知其他线程继续执行。条件变量本身不是锁。条件变量常与互斥锁(mutex)结合使用,以实现线程之间的同步操作。

1. 相关函数:

(1) 对条件变量进行初始化,并可指定属性。通常使用默认属性,可以传入 NULL。

 int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);

(2) 销毁条件变量,释放相关资源。

int pthread_cond_destroy(pthread_cond_t *cond);
  • 当前线程等待条件变量满足,并释放关联的互斥锁。该函数会阻塞线程直至条件变量被通知。
    在调用 pthread_cond_wait() 之前,必须先获得与条件变量关联的互斥锁 mutex 的锁,然后该函数会自动释放 mutex 的锁(自动 unlock),并让线程进入等待状态,直到被另一个线程通过 pthread_cond_signal() 或 pthread_cond_broadcast() 唤醒(自动 lock)。
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);

(3) 通知等待在条件变量上的一个线程,使其继续执行。如果有多个线程等待,只通知其中一个线程。

int pthread_cond_signal(pthread_cond_t *cond);

(4) 通知所有等待在条件变量上的线程,使它们都继续执行。

int pthread_cond_broadcast(pthread_cond_t *cond) ;

2. 示例代码:
描述生产者 和 消费者的关系。

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>struct msg
{int num;struct msg* pnext;
};struct msg *head = NULL;pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;void *producer_thread (void *arg)							// 生产者线程
{while(1){	struct msg *info = malloc(sizeof(struct msg));info->num = rand() % 1000 + 1;pthread_mutex_lock(&mutex);info->pnext = head;head = info;pthread_mutex_unlock(&mutex);// 唤醒阻塞的线程pthread_cond_signal(&cond);			printf("--------------------- producer : %d\n",info->num);sleep(rand() % 3);}return NULL;
}void *customer_thread (void *arg)					// 消费者线程
{while(1){struct msg *info;		pthread_mutex_lock(&mutex);if(head == NULL){pthread_cond_wait(&cond, &mutex);			// 阻塞线程,等待有数据。}info = head;head = info->pnext;pthread_mutex_unlock(&mutex);printf("customer : =============== %d\n",info->num);free(info);info = NULL;sleep(rand() % 3);}return NULL;
}int main(void)
{pthread_t pid,cid;srand(time(NULL));						// 设置随机种子int ret = pthread_create(&pid, NULL, producer_thread, NULL);if(ret != 0){printf("prodecer_thread_create error\n");}ret = pthread_create(&cid, NULL, customer_thread, NULL);if(ret != 0){printf("consumer_thread_create error\n");}pthread_join(pid, NULL);					// 等待回收线程,获取退出线程的状态pthread_join(cid, NULL);pthread_mutex_destroy(&mutex);pthread_cond_destroy(&cond);return 0;
}

总结

相关文章:

Linux多线程同步机制(下)

文章目录 前言一、读写锁二、条件变量总结 前言 一、读写锁 多线程同步机制中的读写锁&#xff08;Read-Write Lock&#xff09;是一种特殊的锁机制&#xff0c;用于控制对共享资源的读写访问。读写锁允许多个线程同时读取共享资源&#xff0c;但在写操作时需要独占访问。 读…...

【QT】ComboBox的使用(14)

ComboBox这个控件我常用于多文本的储存、调用&#xff0c;正如他的中文意思为&#xff1a;下拉列表框。 下拉列表框&#xff1a;字面意思就是一个多文本的列表框&#xff0c;今天来看下如何使用ComboBox这个控件。 一.环境配置 1.python 3.7.8 可直接进入官网下载安装&…...

关于写英文论文的一些总结

名词连接名词组成名词&#xff0c;例如任务名&#xff0c;用task name&#xff0c;而不是name of task。其他各种词也是类似的&#xff1b;本文提出了什么什么&#xff0c;用 this study&#xff1b;多用it is become xx&#xff0c;这种更好&#xff0c;而不是we xx&#xff1…...

swagger 2.10.5 整合 spring boot

参考&#xff1a; http://springfox.github.io/springfox/ https://github.com/springfox/springfox http://springfox.github.io/springfox/docs/current/ https://github.com/springfox/springfox-demos https://github.com/springfox/springfox-demos/tree/2.9.2 https://gi…...

Python 练习:剔除数字

练习&#xff1a;剔除数字&#xff1a; 要求如下&#xff1a; 1、编写一段程序代码&#xff0c;程序运行后&#xff0c; 需要用户随意输入一段包含有数字和字母的字符串&#xff1b; 2、程序会自动删除字符串中的数字&#xff0c; 然后输出一串没有数字的字符串&#xff08;纯…...

Linux系统编程:基础知识入门学习笔记汇总

Linux基础shell编程——>Linux 系统编程——>&#xff08;计算机网络&#xff09;——>Linux 网络编程 来源&#xff1a;黑马程序员-Linux系统编程 45小时 评价 这个老师好像讲了很多课程&#xff0c;都还不错我由于赶时间之前学过Linux的Shell编程和Linux的网络编程&…...

基于硬件隔离增强risc-v调试安全1_问题描述

安全之安全(security)博客目录导读 2023 RISC-V中国峰会 安全相关议题汇总 说明&#xff1a;本文参考RISC-V 2023中国峰会如下议题&#xff0c;版权归原作者所有。...

OpenCV简介

OpenCV简介 OpenCV&#xff08;开源计算机视觉库&#xff1a;http://opencv.org&#xff09;是一个开源库&#xff0c;包含数百种计算机视觉算法。OpenCV 具有模块化结构&#xff0c;主要包括下列模块&#xff1a; 核心功能&#xff08;core&#xff09; - 定义基本数据结构的…...

Windows下编译qt-src-5.15.10

首先从镜像站点下载qt源码&#xff1a; https://download.qt.io/static/mirrorlist/ 下载QT的镜像站点 下载源码后解压到 F: 盘 创建编译目录F:\qtbuild 打开VS2019的 X64 Native Tools Command Prompt for VS 2019 进入到源码目录 cd F:\qt-everywher…...

有关linux排查服务器资源问题

查看 磁盘占用 df -h 进入到某一个文件夹下 查看对应文件夹占用 du -sh /usr...

【设计模式】Head First 设计模式——观察者模式 C++实现

设计模式最大的作用就是在变化和稳定中间寻找隔离点&#xff0c;然后分离它们&#xff0c;从而管理变化。将变化像小兔子一样关到笼子里&#xff0c;让它在笼子里随便跳&#xff0c;而不至于跳出来把你整个房间给污染掉。 设计思想 主题对象&#xff08;出版者&#xff09;管理…...

【ES】笔记-Promise基本使用

笔记-基本使用 一、初始Promise1. 抽象表达:2. 具体表达:为什么要用 Promise?promise的基本流程 二、fs读取文件三、AJAX请求四、Promise封装fs模块五、util.promisify方法六、Promise封装AJAX操作 一、初始Promise 1. 抽象表达: 1. Promise 是一门新的技术(ES6 规范) 2. Pr…...

服务器数据恢复-reiserfs文件系统损坏如何恢复数据?

服务器数据恢复环境&#xff1a; 一台IBM X系列服务器&#xff0c;4块SAS硬盘组建一组RAID5阵列&#xff0c;采用的reiserfs文件系统。服务器操作系统分区结构&#xff1a;boot分区LVM卷swap分区&#xff08;按照前后顺序&#xff09;。LVM卷中直接划分了一个reiserfs文件系统&…...

直播预告:把脉2023年下半场—主动防御邮箱盗号威胁

长期以来&#xff0c;承载着大量敏感数据的企业是黑产团伙的首要攻击目标。Coremail结合多年以来的邮件防护经验发现&#xff0c;黑产团伙针对企业邮箱账号安全的两大攻击方式为暴力破解和钓鱼邮件攻击。 一、企业邮箱安全现状 01、使用弱密码 企业员工使用弱密码让黑产团伙有…...

专题:平面、空间直线参数方程下的切线斜率问题

本文研究平面、空间直线在参数方程形式下&#xff0c;切线斜率&#xff08;即导数&#xff09;如何表示的问题。 如上图所示。 设 y f ( x ) &#xff0c; x φ ( t ) &#xff0c; y ψ ( t ) 当 t t 0 时&#xff0c; x x 0 &#xff0c; y y 0 &#xff0c;即点 A 坐…...

JavaScript—对象与构造方法

目录 json对象&#xff08;字面值&#xff09; js中对象是什么&#xff1f; 如何使用&#xff1f; 关联数组 js对象和C#对象有什么区别&#xff1f; 构造函数 什么是构造方法&#xff1f; 如何使用构造方法&#xff1f; 如何添加成员&#xff1f; 对象的动态成员 正则…...

微信小程序社区户口管理的系统设计与实现

摘要 我国的户口管理制度由来已久&#xff0c;我国对于合法居民在新生儿的出生、户口的落地、迁移以及户口的注销上都有着详细的管理条例进行约束。通过户口的管理可以更好地对我国的居民人数进行有效的内容统计&#xff0c;在进行人口普查的过程中也能够实现更好的、更加精准的…...

闲人闲谈PS之四十六——网络生产全流程

惯例闲话&#xff1a;下半年已开始块行情似乎又是一波大涨&#xff0c;很多朋友委托我介绍PS顾问&#xff0c;很多朋友已经上了能源系统项目&#xff0c;这就造成装备制造的PS又是极度紧缺&#xff0c;rate也还可以&#xff0c;搞的自己也有点心痒痒。这种逆势大涨&#xff0c;…...

如何在VR头显端实现低延迟的RTSP或RTMP播放

技术背景 VR&#xff08;虚拟现实技术&#xff09;给我们带来身临其境的视觉体验&#xff0c;广泛的应用于城市规划、教育培训、工业仿真、房地产、水利电力、室内设计、文旅、军事等众多领域&#xff0c;常用的行业比如&#xff1a; 教育行业&#xff1a;VR头显可以用于教育…...

【工具类】提高办公效率(兼具有趣、好玩)

1 Wormhole 免费免注册登录在线、不限速文件传输 Simple, private file sharing https://wormhole.app/ 2 ALL to ALL 在线格式转换 免费、免注册登录 国内最全类型的在线文件转换平台&#xff0c;免费、快速&#xff0c;无须下载安装任何软件。 https://www.alltoall.net/ …...

Ubuntu系统下交叉编译openssl

一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机&#xff1a;Ubuntu 20.04.6 LTSHost&#xff1a;ARM32位交叉编译器&#xff1a;arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

mongodb源码分析session执行handleRequest命令find过程

mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程&#xff0c;并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令&#xff0c;把数据流转换成Message&#xff0c;状态转变流程是&#xff1a;State::Created 》 St…...

java 实现excel文件转pdf | 无水印 | 无限制

文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...

拉力测试cuda pytorch 把 4070显卡拉满

import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试&#xff0c;通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小&#xff0c;增大可提高计算复杂度duration: 测试持续时间&#xff08;秒&…...

零基础设计模式——行为型模式 - 责任链模式

第四部分&#xff1a;行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习&#xff01;行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想&#xff1a;使多个对象都有机会处…...

Web 架构之 CDN 加速原理与落地实践

文章目录 一、思维导图二、正文内容&#xff08;一&#xff09;CDN 基础概念1. 定义2. 组成部分 &#xff08;二&#xff09;CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 &#xff08;三&#xff09;CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 &#xf…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题

分区配置 (ptab.json) img 属性介绍&#xff1a; img 属性指定分区存放的 image 名称&#xff0c;指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件&#xff0c;则以 proj_name:binary_name 格式指定文件名&#xff0c; proj_name 为工程 名&…...

云安全与网络安全:核心区别与协同作用解析

在数字化转型的浪潮中&#xff0c;云安全与网络安全作为信息安全的两大支柱&#xff0c;常被混淆但本质不同。本文将从概念、责任分工、技术手段、威胁类型等维度深入解析两者的差异&#xff0c;并探讨它们的协同作用。 一、核心区别 定义与范围 网络安全&#xff1a;聚焦于保…...

boost::filesystem::path文件路径使用详解和示例

boost::filesystem::path 是 Boost 库中用于跨平台操作文件路径的类&#xff0c;封装了路径的拼接、分割、提取、判断等常用功能。下面是对它的使用详解&#xff0c;包括常用接口与完整示例。 1. 引入头文件与命名空间 #include <boost/filesystem.hpp> namespace fs b…...

大数据驱动企业决策智能化的路径与实践

&#x1f4dd;个人主页&#x1f339;&#xff1a;慌ZHANG-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 一、引言&#xff1a;数据驱动的企业竞争力重构 在这个瞬息万变的商业时代&#xff0c;“快者胜”的竞争逻辑愈发明显。企业如何在复杂环…...