Linux -- 同步与条件变量

目录

同步

条件变量

pthread_cond_t

pthread_cond_init(初始化条件变量)

pthread_cond_destroy(销毁条件变量)

pthread_cond_wait(线程等待条件变量)

重要提醒 

pthread_cond_boardcast(唤醒等待队列中的所有线程)

pthread_cond_singal(唤醒一个正在等待的线程)

代码

条件变量的使用

唤醒一个线程:

广播唤醒线程:


同步

在保证数据安全的前提下,让线程能够按照某种特定的顺序访问临界资源,确保这些执行单元以一种有序、非冲突的方式进行交互,从而有效避免饥饿问题,叫做同步

条件变量

条件变量的主要用途是用于实现同步,在一个或多个线程等待某个特定条件变为真时,可以被阻塞(挂起),直到其他线程通知这个条件已经满足。它提供了一种机制来安全地等待某个条件,并在条件满足时唤醒等待的线程。条件变量通常与互斥锁pthread_mutex_t)一起使用,以保护共享资源和确保线程安全。

条件变量其实是一种通知机制 + 等待队列

  • 当某种特定的条件未成立时,线程在等待队列中排队
  • 当条件成立时,可以选择唤醒队头的线程或者队列中的所有线程,继续执行线程任务。

pthread_cond_t

线程库中用于条件变量的一种数据类型

pthread_cond_init(初始化条件变量)

#include <pthread.h>int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr);

cond:指向要初始化的条件变量的指针。

attr:指向条件变量属性对象的指针。如果只需要默认属性,可以传递 NULL

 返回值:

  • 成功时,返回 0
  • 失败时,返回错误编号。

pthread_cond_destroy(销毁条件变量)

#include <pthread.h>int pthread_cond_destroy(pthread_cond_t *cond);

cond:指向要销毁的条件变量的指针。

返回值:

  • 成功时,返回 0
  • 失败时,返回错误编号。

pthread_cond_wait(线程等待条件变量)

#include <pthread.h>int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);

cond:指向要等待的条件变量的指针。

mutex:指向已经加锁的互斥锁的指针。该互斥锁应该保护着与条件相关的共享数据。

返回值:

  • 成功时,返回 0
  • 失败时,返回错误编号。

重要提醒 

  • 在调用 pthread_cond_wait 时,当前线程必须持有由 mutex 指向的互斥锁。
  • 调用此函数后,pthread_cond_wait 会自动释放互斥锁,并将当前线程置为等待状态直到某个其他线程调用 pthread_cond_signal 或 pthread_cond_broadcast 来唤醒它。
  • 当前线程被唤醒后,pthread_cond_wait 会重新尝试获取互斥锁;只有成功获取到互斥锁之后,函数才会返回。
  • 返回时,互斥锁再次被当前线程持有

pthread_cond_boardcast(唤醒等待队列中的所有线程)

#include <pthread.h>int pthread_cond_broadcast(pthread_cond_t *cond);

cond:指向要广播信号的条件变量的指针。

返回值:

  • 成功时,返回 0
  • 失败时,返回错误编号。
  • 当调用 pthread_cond_broadcast 时,所有当前正在等待该条件变量的线程都会被唤醒。
  • 每个被唤醒的线程在继续执行之前会重新尝试获取与条件变量关联的互斥锁。
  • 注意,这并不意味着所有被唤醒的线程都会立即运行;它们仍然需要按照操作系统的调度算法来获得CPU时间。

pthread_cond_singal(唤醒一个正在等待的线程)

#include <pthread.h>int pthread_cond_signal(pthread_cond_t *cond);

cond:指向要发出信号的条件变量的指针。

返回值:

  • 成功时,返回 0
  • 失败时,返回错误编号。
  • 当调用 pthread_cond_signal 时,如果有线程正在等待该条件变量,则会唤醒其中一个线程。
  • 被唤醒的线程在继续执行之前会重新尝试获取与条件变量关联的互斥锁。
  • 如果没有线程在等待该条件变量,那么调用 pthread_cond_signal 将不会有任何效果。 

代码

条件变量的使用

条件变量通常与互斥锁配套使用,线程持有互斥锁了,才可以去检查某个特定的条件是否满足,满足了才能去访问临界资源,如果不满足就去排队,所以条件变量一般在加锁和解锁之间使用,所以在排队的线程曾经拥有互斥锁

线程去排队时,需要把曾经申请到的互斥锁释放掉,让其他线程去申请锁,线程不可以拿着锁去排队,否则无法达到同步,无法保持良好的并发性!所以 pthread_cond_wait 函数的参数还包括指向已经加锁的互斥锁的指针,就是为了把线程曾经申请到的互斥锁释放掉!

唤醒一个线程:

#include<iostream>
#include<string>
#include<vector>
#include<unistd.h>pthread_cond_t gcond=PTHREAD_COND_INITIALIZER;//条件变量
pthread_mutex_t gmutex=PTHREAD_MUTEX_INITIALIZER;//互斥锁void* SlaverCore(void* args)
{std::string name=static_cast<const char*>(args);//被唤醒while(true){pthread_mutex_lock(&gmutex);//加锁//一般条件变量在加锁与解锁之间使用pthread_cond_wait(&gcond,&gmutex);//等待成功,被唤醒了std::cout<<"当前被唤醒的线程为:"<<name<<std::endl;pthread_mutex_unlock(&gmutex);//解锁}
}
void* MasterCore(void* args)
{sleep(3);std::cout<<"master 开始工作..."<<std::endl;//唤醒while(true){pthread_cond_signal(&gcond);std::cout<<"master 唤醒线程..."<<std::endl;sleep(1);}
}//创建一批被控制的线程
void StartSlaver(std::vector<pthread_t> *tidsptr,int num=3)
{for(int i=0;i<num;i++){pthread_t tid;char *name=new char[64];snprintf(name,64,"slaver-%d",i+1);int n=pthread_create(&tid,nullptr,SlaverCore,name);if(n==0){std::cout<<"create success: "<<name<<std::endl;tidsptr->emplace_back(tid);}}
}//创建主线程
void StartMaster(std::vector<pthread_t> *tidsptr)
{pthread_t tid;int n=pthread_create(&tid,nullptr,MasterCore,nullptr);if(n==0)//创建成功{std::cout<<"create master success"<<std::endl;}tidsptr->emplace_back(tid);
}void WaitThread(std::vector<pthread_t> tids)
{for(auto &tid:tids){pthread_join(tid,nullptr);//等待线程}
}
int main()
{std::vector<pthread_t> tids;//存线程idStartMaster(&tids);StartSlaver(&tids,5);WaitThread(tids);return 0;
}

广播唤醒线程:

#include<iostream>
#include<string>
#include<vector>
#include<unistd.h>pthread_cond_t gcond=PTHREAD_COND_INITIALIZER;//条件变量
pthread_mutex_t gmutex=PTHREAD_MUTEX_INITIALIZER;//互斥锁void* SlaverCore(void* args)
{std::string name=static_cast<const char*>(args);//被唤醒while(true){pthread_mutex_lock(&gmutex);//加锁//一般条件变量在加锁与解锁之间使用pthread_cond_wait(&gcond,&gmutex);//等待成功,被唤醒了std::cout<<"当前被唤醒的线程为:"<<name<<std::endl;pthread_mutex_unlock(&gmutex);//解锁}
}
void* MasterCore(void* args)
{sleep(3);std::cout<<"master 开始工作..."<<std::endl;//唤醒while(true){pthread_cond_broadcast(&gcond);std::cout<<"master 唤醒线程..."<<std::endl;sleep(1);}
}//创建一批被控制的线程
void StartSlaver(std::vector<pthread_t> *tidsptr,int num=3)
{for(int i=0;i<num;i++){pthread_t tid;char *name=new char[64];snprintf(name,64,"slaver-%d",i+1);int n=pthread_create(&tid,nullptr,SlaverCore,name);if(n==0){std::cout<<"create success: "<<name<<std::endl;tidsptr->emplace_back(tid);}}
}//创建主线程
void StartMaster(std::vector<pthread_t> *tidsptr)
{pthread_t tid;int n=pthread_create(&tid,nullptr,MasterCore,nullptr);if(n==0)//创建成功{std::cout<<"create master success"<<std::endl;}tidsptr->emplace_back(tid);
}void WaitThread(std::vector<pthread_t> tids)
{for(auto &tid:tids){pthread_join(tid,nullptr);//等待线程}
}
int main()
{std::vector<pthread_t> tids;//存线程idStartMaster(&tids);StartSlaver(&tids,5);WaitThread(tids);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/890645.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【源码编译】windows下mingw64安装以及cmake调用

最近因为安装MIRTK库&#xff0c;太多第三方依赖了&#xff0c;太折磨了&#xff0c;学习了使用Cmake&#xff0c;有些库又需要Fortran编译器&#xff0c;VS2022里面装了但又调用不了&#xff0c;也不知道为什么&#xff0c;最后装的mingw64&#xff0c;记录一下。 1、mingw64安…

6、mysql的MHA故障切换

MHA的含义 MHA&#xff1a;master high availability&#xff0c;建立在主从复制基础上的故障切换的软件系统。 主从复制的单点问题&#xff1a; 当主从复制当中&#xff0c;主服务器发生故障&#xff0c;会自动切换到一台从服务器&#xff0c;然后把从服务器升格成主&…

LeetCode:104.二叉树的最大深度

跟着carl学算法&#xff0c;本系列博客仅做个人记录&#xff0c;建议大家都去看carl本人的博客&#xff0c;写的真的很好的&#xff01; 代码随想录 LeetCode&#xff1a;104.二叉树的最大深度 给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节…

WebRTC服务质量(12)- Pacer机制(04) 向Pacer中插入数据

WebRTC服务质量&#xff08;01&#xff09;- Qos概述 WebRTC服务质量&#xff08;02&#xff09;- RTP协议 WebRTC服务质量&#xff08;03&#xff09;- RTCP协议 WebRTC服务质量&#xff08;04&#xff09;- 重传机制&#xff08;01) RTX NACK概述 WebRTC服务质量&#xff08;…

双指针——快乐数

一.题目描述 202. 快乐数 - 力扣&#xff08;LeetCode&#xff09; 二.题目解析 我们要判断一个数是不是快乐数要通过它的三个性质来进行判断。这个数会一直变化&#xff0c;由它的各个位的平方和重新构成这个数。如果这个数在变化的过程中变成了1&#xff0c;那么就是快乐数…

【玩转OCR】 | 腾讯云智能结构化OCR在多场景的实际应用与体验

文章目录 引言产品简介产品功能产品优势 API调用与场景实践图像增强API调用实例发票API调用实例其他场景 结语相关链接 引言 在数字化信息处理的时代&#xff0c;如何高效、精准地提取和结构化各类文档数据成为了企业和政府部门的重要需求。尤其是在面对海量票据、证件、表单和…

nginx-rtmp服务器搭建

音视频服务器搭建 本文采用 nginx/1.18.0和nginx-rtmp-module模块源代码搭建RTMP流媒体服务器 流程 查看当前服务器的nginx版本下载nginx和nginx-rtmp-module源代码重新编译nginx&#xff0c;并进行相关配置&#xff08;nginx.conf、防火墙等&#xff09;客户端测试连接测试搭…

借助Aspose.html控件, 使用 Java 编程将 HTML 转换为 BMP

Aspose.HTML for .NET 不仅提供超文本标记语言 ( HTML ) 文件处理&#xff0c;还提供流行图像文件格式之间的转换。您可以利用丰富的渲染和转换功能将SVG文件渲染为PNG、JPG或其他广泛使用的文件格式。但是&#xff0c;我们将使用此C# 图像处理库以编程方式在 C# 中将 SVG 转换…

区块链期末复习1.1:密码学哈希函数

一、哈希函数应该具备的三个特性 1.输入可以为任意长度的字符串 2.产生固定大小输出&#xff08;比如256位&#xff09; 3.能进行有效计算。对于n位字符串&#xff0c;可以在O(n)的时间内计算出哈希值。 二.加密哈希函数的三个特性 1.collision-resistance(碰撞阻力&#x…

华为:数字化转型只有“起点”,没有“终点”

上个月&#xff0c;我收到了一位朋友的私信&#xff0c;他询问我是否有关于华为数字化转型的资料。幸运的是&#xff0c;我手头正好收藏了一些&#xff0c;于是我便分享给他。 然后在昨天&#xff0c;他又再次联系我&#xff0c;并感慨&#xff1a;“如果当初我在进行企业数字…

Android基于Path的addRoundRect,Canvas剪切clipPath简洁的圆形图实现,Kotlin(2)

Android基于Path的addRoundRect&#xff0c;Canvas剪切clipPath简洁的圆形图实现&#xff0c;Kotlin&#xff08;2&#xff09; import android.content.Context import android.graphics.BitmapFactory import android.graphics.Canvas import android.graphics.Path import a…

中化信息与枫清科技深化合作:共探“AI+”产业新生态

随着数字化转型的浪潮席卷全球&#xff0c;数据已成为推动创新和经济增长的关键力量。为持续深化数据要素价值挖掘与应用实践&#xff0c;推动打造行业交流平台&#xff0c;驱动产业创新共荣&#xff0c;2024 年 12 月 18 日 -19 日&#xff0c;由中国通信标准化协会主办的“20…

Matrix-Breakout 2 Morpheus

第一步 信息收集 (1)寻找靶场真实ip arp-scan -l 靶场真实 ip 为192.168.152.154 (2)探测端口及服务 nmap -p- -sV 192.168.52.135 第二步 开始渗透 (1)访问web服务 http://192.168.152.154and http://192.168.52.135:81 发现 81 端口的页面要登录 我们使用 dirb 扫描…

我的AI工具箱Tauri版-ZoomImageSUPIR图像超细节缩放

本教程基于自研的AI工具箱Tauri版进行ZoomImageSUPIR图像超细节缩放。 ZoomImageSUPIR图像超细节缩放 是一款专为图像处理优化的工具&#xff0c;支持图像的高精度放大与缩小操作&#xff0c;满足多场景需求。通过集成 SUPIR&#xff08;Super-resolution Image Processing wi…

软件工程-【软件项目管理】--期末复习题汇总

一、单项选择题 &#xff08;1&#xff09;赶工一个任务时&#xff0c;你应该关注&#xff08; C &#xff09; A. 尽可能多的任务 B. 非关键任务 C. 加速执行关键路径上的任务 D. 通过成本最低化加速执行任务 &#xff08;2&#xff09;下列哪个不是项目管理计划的一部分&…

访问ipv6的坑

如何访问ipv6站点 本机ipv6回环地址: http://[0:0:0:0:0:0:0:1]:8080/index.html 类似ipv4的127.0.0.1 查看本机的ipv6地址 使用ipconfig命令查看 ac900::27bf:9999:6950:dfa7%15需要去掉%符号后面的内容 ac900::27bf:9999:6950:dfa http://[ac900::27bf:9999:6950:dfa]:80…

Java对象的内存分布(一)

一、概览 在Hotspot虚拟机中&#xff0c;java对象在内存中分布如下图所示&#xff1a; --------------------------------------------- | 对象头 | 实例数据 | 对齐填充 | --------------------------------------------- 对象大小 对象头 实例数据 [填…

RY2200 One Cell Li-ion and Li-poly Battery Protection IC

1、Features Protection ofCharger Reverse Connection 50mΩ Low RssoN) Internal Power MOSFET Protection of Battery Cell Reverse Connection Delay Times are generated inside Over-temperature Protection …

H3C MPLS跨域optionB

实验拓扑 实验需求 如图,VPN1 和 VPN2 分别通过运营商 MPLS VPN 连接各自分支机构按照图示配置 IP 地址,VPN1 和 VPN2 连接同一个 PE 设备的私网 IP 网段存在地址复用,使用多 VRF 技术来防止 IP 冲突AS 100 和 AS 200 内部的公共网络中各自运行 OSPF 使 AS 内各设备的 Loo…

harmony动画属性

属性动画 显式动画 转场动画