Linux线程同步(条件变量)

文章目录

  • 前言
  • 一、条件变量概念
  • 二、条件变量相关的函数
  • 三、条件变量模拟生产者消费者模型
  • 四、使用条件变量的好处
  • 总结


前言

本篇文章来讲解一下条件变量的使用。

一、条件变量概念

条件变量(Condition Variable)是并发编程中一种线程同步机制,用于实现线程之间的等待和通知机制。它是一种与特定条件相关的线程同步原语。

条件变量用于线程间的协调,允许一个线程在满足某个特定条件之前等待,并在其他线程满足条件后被通知继续执行。它通常与互斥锁(Mutex)结合使用,以提供更精细的线程同步和共享数据的访问控制。

条件变量的基本概念包括以下几个要素:

1.等待和通知:
条件变量提供了等待和通知的机制,等待(Wait)操作用于使线程进入等待状态,直到满足某个特定条件。通知(Signal或Broadcast)操作用于唤醒等待中的线程,告知它们条件已经满足。

2.互斥锁:
在使用条件变量之前,通常需要先获取与之配套的互斥锁,以确保共享数据的互斥访问。互斥锁用于保护与条件相关的共享资源,以防止多个线程同时访问。

3.条件谓词:
条件变量通常与条件谓词(Condition Predicate)一起使用,条件谓词是描述条件是否满足的谓词表达式。在线程等待之前和通知之后,都需要通过条件谓词进行条件的检查。

条件变量的典型用法包括以下步骤:

1.线程获取互斥锁,锁定共享资源。

2.检查条件谓词,判断是否满足等待条件,如果不满足则等待条件变量。

3.线程释放互斥锁并进入等待状态,直到其他线程发出通知。

4.当其他线程满足条件变量的条件并发出通知时,等待中的线程被唤醒。

5.线程重新获取互斥锁,继续执行后续操作。

条件变量的使用可以避免线程的忙等待,提高程序的效率,并且更加灵活地实现线程间的通信和同步。但在使用条件变量时需要注意正确的加锁和解锁的顺序,以避免死锁和竞态条件等并发编程的常见问题。

二、条件变量相关的函数

条件变量在Linux下使用一些常见的函数来实现线程之间的同步和通信。下面是条件变量使用的几个常用函数:

1.pthread_cond_init():用于初始化条件变量。‘

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

参数 cond:指向要初始化的条件变量。
参数 attr:指向条件变量的属性对象,通常传递 NULL。
返回值:成功返回0,失败返回错误码。

2.pthread_cond_destroy():用于销毁条件变量。

int pthread_cond_destroy(pthread_cond_t *cond);

参数 cond:指向要销毁的条件变量。
返回值:成功返回0,失败返回错误码。

3.pthread_cond_wait():用于等待条件变量满足条件。

int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);

参数 cond:指向要等待的条件变量。
参数 mutex:指向与条件变量关联的互斥锁。
返回值:成功返回0,失败返回错误码。
在调用 pthread_cond_wait() 之前,必须先获得与条件变量关联的互斥锁 mutex 的锁,然后该函数会自动释放 mutex 的锁,并让线程进入等待状态,直到被另一个线程通过 pthread_cond_signal() 或 pthread_cond_broadcast() 唤醒。

4.pthread_cond_signal():用于唤醒一个正在等待条件变量的线程。

int pthread_cond_signal(pthread_cond_t *cond);

参数 cond:指向要唤醒的条件变量。
返回值:成功返回0,失败返回错误码。
pthread_cond_signal() 会唤醒等待 cond 条件变量的一个线程,如果没有线程在等待条件变量,则该函数调用没有任何效果。

5.pthread_cond_broadcast():用于唤醒所有正在等待条件变量的线程。

int pthread_cond_broadcast(pthread_cond_t *cond);

参数 cond:指向要广播的条件变量。
返回值:成功返回0,失败返回错误码。
pthread_cond_broadcast() 会唤醒等待 cond 条件变量的所有线程,即广播唤醒所有等待的线程。

三、条件变量模拟生产者消费者模型

示例代码:

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>#define BUFFER_SIZE 10typedef struct {int buffer[BUFFER_SIZE];int count;int in;int out;pthread_mutex_t mutex;pthread_cond_t cond;
} Buffer;Buffer buffer;void* producer(void* arg) 
{int item = 1;while (1) {pthread_mutex_lock(&buffer.mutex);// 检查缓冲区是否已满while (buffer.count == BUFFER_SIZE) {pthread_cond_wait(&buffer.cond, &buffer.mutex);}// 写入数据并更新缓冲区状态buffer.buffer[buffer.in] = item;buffer.in = (buffer.in + 1) % BUFFER_SIZE;buffer.count++;printf("生产者生产了:%d\n", item);// 唤醒等待的消费者线程pthread_cond_signal(&buffer.cond);pthread_mutex_unlock(&buffer.mutex);item++;sleep(1);}return NULL;
}void* consumer(void* arg) 
{while (1) {pthread_mutex_lock(&buffer.mutex);// 检查缓冲区是否为空while (buffer.count == 0) {pthread_cond_wait(&buffer.cond, &buffer.mutex);}// 读取数据并更新缓冲区状态int item = buffer.buffer[buffer.out];buffer.out = (buffer.out + 1) % BUFFER_SIZE;buffer.count--;printf("消费者消费了:%d\n", item);// 唤醒等待的生产者线程pthread_cond_signal(&buffer.cond);pthread_mutex_unlock(&buffer.mutex);sleep(1);}return NULL;
}int main(void)
{pthread_t producer_thread, consumer_thread;// 初始化缓冲区和相关的同步对象buffer.count = 0;buffer.in = 0;buffer.out = 0;pthread_mutex_init(&buffer.mutex, NULL);pthread_cond_init(&buffer.cond, NULL);// 创建生产者线程和消费者线程pthread_create(&producer_thread, NULL, producer, NULL);pthread_create(&consumer_thread, NULL, consumer, NULL);// 等待线程结束pthread_join(producer_thread, NULL);pthread_join(consumer_thread, NULL);// 销毁同步对象pthread_mutex_destroy(&buffer.mutex);pthread_cond_destroy(&buffer.cond);return 0;
}

运行效果:
在这里插入图片描述

四、使用条件变量的好处

1.避免资源浪费:当条件不满足时,线程可以调用pthread_cond_wait函数来等待条件满足。在等待期间,该线程会释放持有的锁,允许其他线程获得锁并继续执行临界区代码。这样可以避免空转和资源浪费。

2.避免竞争条件:条件变量的使用可以帮助避免竞争条件的发生。线程间的协作通过条件变量来实现,确保在满足特定条件之前,线程不会执行关键代码段。

3.提高并发性:条件变量使得线程能够在需要等待条件满足时休眠,而不是通过忙等待消耗处理器资源。这样可以提高系统的并发性和效率。

4.简化同步逻辑:使用条件变量可以简化同步逻辑,使代码更加清晰易懂。条件变量提供了一种灵活而有效的机制来控制线程的行为,使得编写正确的多线程代码变得更加容易。

总结

本篇文章主要讲解了条件变量的概念和条件变量的相关函数和使用条件变量模拟生产者消费者模型。

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

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

相关文章

如何在页面中嵌入音频和视频?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 嵌入音频⭐ 嵌入视频⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏…

如何实现 Java SpringBoot 自动验证入参数据的有效性

Java SpringBoot 通过javax.validation.constraints下的注解&#xff0c;实现入参数据自动验证 如果碰到 NotEmpty 否则不生效&#xff0c;注意看下 RequestBody 前面是否加上了Valid Validation常用注解汇总 Constraint详细信息Null被注释的元素必须为 nullNotNull被注释的元…

chatGLM 本地部署(windows+linux)

chatGLM算是个相对友好的模型&#xff0c;支持中英文双语的对话交流&#xff0c;清华出的 我的教程无需特别的网络设置&#xff0c;不过部分情况因为国内网络速度慢&#xff0c;需要反复重复 chatGLM github地址 一、硬件需求 N卡8G显存以上&#xff0c;最好16G以上&#xff…

AI 绘画Stable Diffusion 研究(六)sd提示词插件

大家好&#xff0c;我是风雨无阻。 今天为大家推荐一款可以有效提升我们使用 Stable Diffusion WebUI 效率的插件&#xff0c; 它就是 prompt-all-in-one&#xff0c; 它不但能直接将 WebUI 中的中文提示词转换为英文&#xff0c;还能一键为关键词加权重&#xff0c;更能建立常…

公众号外包开发框架

公众号开发框架主要指的是在微信公众号平台上开发应用的技术框架。微信公众号是一种基于微信平台的应用&#xff0c;分为订阅号、服务号和企业号&#xff08;现在称为企业微信&#xff09;等不同类型。以下是一些常见的公众号开发框架以及它们的特点&#xff0c;希望对大家有所…

【Hystrix技术指南】(5)Command创建和执行实现

创建流程 构建HystrixCommand或者HystrixObservableCommand对象 *使用Hystrix的第一步是创建一个HystrixCommand或者HystrixObservableCommand对象来表示你需要发给依赖服务的请求。 若只期望依赖服务每次返回单一的回应&#xff0c;按如下方式构造一个HystrixCommand即可&a…

hive修改表或者删除表时卡死问题的解决(2023-08-08)

背景&#xff1a;前阶段在做hive表的改表名时&#xff0c;总是超时&#xff0c;表是内部表&#xff0c;数据量特别大&#xff0c;无论你是修改表名还是删除表都是卡死的状态&#xff0c;怎么破&#xff1f; 终于&#xff1a;尝试出来一个新的方法 将内部表转化成外部表&#…

pytest之测试用例执行顺序

前言 在unittest框架中&#xff0c;默认按照ACSII码的顺序加载测试用例并执行&#xff0c;顺序为&#xff1a;09、AZ、a~z&#xff0c;测试目录、测试模块、测试类、测试方法/测试函数都按照这个规则来加载测试用例。 而 pytest 中的用例执行顺序与unittest 是不一样的&#…

string模拟实现:

string模拟实现&#xff1a; 上一篇博客&#xff0c;我们对String类有了一个基本的认识&#xff0c;本篇博客我们来从0~1去模拟实现一个String类&#xff0c;当然我们实现的都是一些常用的接口。 ❓我们这里定义了一个string类型&#xff0c;然后STL标准库里面也有string&#…

[C#] 简单的俄罗斯方块实现

一个控制台俄罗斯方块游戏的简单实现. 已在 github.com/SlimeNull/Tetris 开源. 思路 很简单, 一个二维数组存储当前游戏的方块地图, 用 bool 即可, true 表示当前块被填充, false 表示没有. 然后, 抽一个 “形状” 类, 形状表示当前玩家正在操作的一个形状, 例如方块, 直线…

测试 tensorflow 1.x 的一个demo 01

tensorflow 1.0的示例代码 demo_01.py import tensorflow as tf import os os.environ[TF_CPP_MIN_LOG_LEVEL]2def tf114_demo():a 3b 4c a bprint("a b in py ",c)a_t tf.constant(3)b_t tf.constant(4)c_t a_t b_tprint("TensorFlow add a_t b_t &…

海外直播种草短视频购物网站巴西独立站搭建

一、市场调研 在搭建网站之前&#xff0c;需要进行充分的市场调研&#xff0c;了解巴西市场的消费者需求、购物习惯和竞争情况。可以通过以下途径进行市场调研&#xff1a; 调查问卷&#xff1a;可以在巴西市场上发放调查问卷&#xff0c;了解消费者的购物习惯、偏好、购买力…

使用langchain与你自己的数据对话(五):聊天机器人

之前我已经完成了使用langchain与你自己的数据对话的前四篇博客&#xff0c;还没有阅读这四篇博客的朋友可以先阅读一下&#xff1a; 使用langchain与你自己的数据对话(一)&#xff1a;文档加载与切割使用langchain与你自己的数据对话(二)&#xff1a;向量存储与嵌入使用langc…

docker容器监控:Cadvisor +Prometheus+Grafana的安装部署

目录 Cadvisor PrometheusGrafana的安装部署 一、安装docker&#xff1a; 1、安装docker-ce 2、阿里云镜像加速器 3、下载组件镜像 4、创建自定义网络 二、部署Cadvisor 1、被监控主机上部署Cadvisor容器 2、访问cAdvisor页面 三、安装prometheus 1、部署Prometheus…

第一天 什么是CSRF ?

✅作者简介&#xff1a;大家好&#xff0c;我是Cisyam&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Cisyam-Shark的博客 &#x1f49e;当前专栏&#xff1a; 每天一个知识点 ✨特色专…

使用Pytest集成Allure生成漂亮的图形测试报告

目录 前言 依赖包安装 Pytest Allure Pytest Adaptor 改造基于Pytest的测试用例 生成测试报告 运行测试 生成测试报告 打开测试报告 资料获取方法 前言 之前写过一篇生成测试报告的博客&#xff0c;但是其实Allure首先是一个可以独立运行的测试报告生成框架&#xff…

中小企业在数字化转型上所面对的问题都有哪些?_光点科技

随着科技的飞速发展&#xff0c;数字化转型已经成为企业持续发展的必由之路。尤其是中小企业&#xff0c;数字化转型不仅可以提高效率&#xff0c;降低成本&#xff0c;还可以拓展市场&#xff0c;增强竞争力。然而&#xff0c;数字化转型并非一帆风顺&#xff0c;中小企业在这…

kubeasz在线安装K8S集群单master

1.基础系统配置 确保在干净的系统上开始安装&#xff0c;不能使用曾经装过kubeadm或其他k8s发行版的环境 系统是Ubuntu 或者CentOS 7 2.下载文件 2.1 下载工具脚本ezdown&#xff0c;举例使用kubeasz版本3.5.0 #此版本默认安装的是 K8S v1.26.0 export release3.5.0 wget h…

C语言数组第十课---------------三子棋-------数组经典练手题

作者前言 &#x1f382; ✨✨✨✨✨✨&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f382; &#x1f382; 作者介绍&#xff1a; &#x1f382;&#x1f382; &#x1f382;…