Linux: 线程同步

目录

一 前言

二 线程饥饿

三 线程同步

四 条件变量

1. cond ( condition)

2. pthread_cond_wait() :

3. pthread_cond_signal()

 五 条件变量的使用


一 前言

 在上篇文章Linux : 多线程互斥-CSDN博客我们讲解了线程互斥的概念,为了防止多个线程同时访问一份临界资源而出问题,我们引入了线程互斥,线程互斥其实就是多个线程同时争抢一份资源,谁抢到了就是谁的,抢不到的只能等待着下一次抢。虽然解决了多个线程同时访问同一资源所产生的问题,但是我们思考一下这样子合理吗?不合理,这会产生另一种问题——线程饥饿


二 线程饥饿

 那么线程饥饿是什么呢?为了便于理解,我们可以极端的考虑问题,假设在多线程情况下,存在着两类优先级不同的线程,一类线程的优先级非常高,另一类的线程的优先级非常低,他们开始同时争抢临界资源,假设高优先级的线程拿到了资源,上了锁之后,其他的线程只能等。直到该线程使用完临近资源后解锁,接着所有线程又开始争抢资源,而高优先级的线程因为其优先性会再一次争抢到资源,如循环往复,导那些低优先级的线程总是在等待中,永远拿不到或者很少次数拿到资源,这样被称为饥饿或者饿死。这种争抢临界资源的方式虽然是没有什么错误,但是总归来说是不合理的。


三 线程同步

在线程只使用互斥的方式去访问临界资源的时候,就可能会出现某些线程饥饿的情况。那么在操作系统中有没有一种机制,在某一时刻既可以只让一个线程去访问临界资源,但是又可以让所有的的线程按照一定的顺序访问资源呢?所有的线程就像排队一样一个个轮流访问资源,当某一线程访问玩临界资源的时候,他就去队尾等待。这样所有的线程的执行流都可以访问到资源,从而杜绝了线程饥饿的问题。  这样的机制叫做——同步,即线程同步:在保证临界资源安全的前提下,让执行流访问临界资源具有一定的顺序性。


四 条件变量

 那么同步是怎么实现的呢?同步离不开一个东西——条件变量条件变量是一种可以实现线程同步的机制,通过条件变量,可以实现让线程有序的访问临界资源

条件变量,顾名思义它是一个执行的“条件”,当线程需要访问临界资源时,如果临界资源不满足一定的条件,那就让线程进行等待,如果满足条件,则让线程继续恢复执行的机制。它是 一个 pthread_cond_t 结构体类型的变量,并且在 pthread 库中也提供了一些条件变量相关的接口。


1. cond ( condition)

pthread_cond_t 是定义条件变量的类型。

条件变量的使用是和互斥锁差不多的。 

  • 条件变量的初始化可以和互斥量相同有两种,一种是调用接口 pthread_cond_init() 初始化,第一个参数是条件变量的地址,第二个参数是条件变量的属性(暂时不考虑)。需要注意的是,用该接口初始化的条件变量在不需要使用的时候,需要调用 pthread_cond_destroy() 接口来销毁掉。

  • 使用宏初始化的条件变量就不用手动调用接口来销毁了。

2. pthread_cond_wait() 

条件变量等待的接口

  • 这么多等待的接口中 pthread_cond_wait() 接口是最常用的,它是pthread库提供的使用条件变量等待的接口,线程调用此接口,线程就会立即进入等待。

  • pthread_cond_timedwait() 也是pthread提供给的使用条件变量等待的接口,不过看他的名字也知道它是一种定时让线程等待的接口,即可以通过该接口设置一定的时间,在此时间内让线程等待,如果此时间内,条件满足了,线程就会被自动唤醒,继续执行代码。

  • 我们可以看到这两个接口的参数中都有 互斥锁 ,他们是和互斥锁一起配合使用的。

上面讲到了两个通过条件变量让线程进行等待的接口,既然有等待的接口,那么自然就存在着通过条件变量去唤醒线程的接口。如下

3. pthread_cond_signal()

调用该接口可以让某个通过指定条件变量陷入等待的线程被唤醒。


 五 条件变量的使用

下面我们写个测试使用一下条件变量

#include <iostream>
#include <string>
#include <pthread.h>
#include <unistd.h>int tickets=1000;
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;//定义一个锁
pthread_cond_t cond =PTHREAD_COND_INITIALIZER;//定义一个条件变量void* start_routine(void* args)
{std::string name =static_cast<const char*>(args);while(true){pthread_mutex_lock(&mutex);pthread_cond_wait(&cond,&mutex);std::cout<<name<<" ->"<<tickets--<<std::endl;pthread_mutex_unlock(&mutex);}
}int main()
{//通过条件变量控制线程的执行pthread_t t1,t2;pthread_create(&t1,nullptr,start_routine,(void*)"thread 1");pthread_create(&t2,nullptr,start_routine,(void*)"thread 2");while(true){sleep(1);pthread_cond_signal(&cond);//唤醒该条件下所以的线程std::cout<<"main thread wake up one thread...."<<std::endl;}pthread_join(t1,nullptr);pthread_join(t2,nullptr);return 0;
}

测试结果 

从测试结果可以看到pthread_cond_signal()对线程的唤醒是以一定顺序来进行的。注意,pthread_cond_signal()是一次对一个线程进行唤醒,我们也可以使用                      pthread_cond_broadcast()来唤醒所有的在等待中的线程。 

int main()
{//通过条件变量控制线程的执行pthread_t t1,t2;pthread_create(&t1,nullptr,start_routine,(void*)"thread 1");pthread_create(&t2,nullptr,start_routine,(void*)"thread 2");while(true){sleep(1);//一次唤醒所以线程pthread_cond_broadcast(&cond);//唤醒该条件下所以的线程std::cout<<"main thread wake up one thread...."<<std::endl;}pthread_join(t1,nullptr);pthread_join(t2,nullptr);return 0;
}

 条件变量:通过条件控制线程的执行

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

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

相关文章

MyBatisPlus-QueryWrapper的exists方法拼接SQL中的EXISTS子句

在 MyBatis-Plus 中,QueryWrapper 的 exists 方法用于拼接 SQL 中的 EXISTS 子句,通常用于构 建子查询条件。以下是具体用法和示例: ​​1. 基本语法​​ // 判断是否存在符合条件的记录 queryWrapper.exists(String existsSql); queryWrapper.notExists(String existsSq…

[数据结构]哈希表

目录 1、哈希表 1.1、概念 1.2、冲突 2、哈希函数设计 3、负载因子调节 4、闭散列 5、开散列/哈希桶&#xff08;重点掌握&#xff09; 6、实现哈希桶 6.1、put方法 6.2、HashMap的扩容机制 6.3、get方法 7、HashMap 8、HashSet 8.1、哈希表性能分析 9、hashcod…

VS-Code创建Vue3项目

1 创建工程文件 创建一个做工程项目的文件夹 如&#xff1a;h5vue 2 cmd 进入文件 h5vue 3 输入如下命令 npm create vuelatest 也可以输入 npm create vitelatest 4 输入项目名称 项目名称&#xff1a;自已输入 回车 可以按键盘 a (全选) 回车&#xff1a; Playwright…

linux休眠唤醒流程

1、框架 2、休眠流程 应用层通过echo mem > /sys/power/state写入休眠状态&#xff0c;给一张大概流程图 这个操作对应在kernel/power/main.c的state这个attr的store操作 static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr, …

Mysql--基础知识点--93--两阶段提交

1 两阶段提交 以update语句的具体执行过程为例&#xff1a; 具体更新一条记录 UPDATE t_user SET name ‘xiaolin’ WHERE id 1;的流程如下&#xff1a; 1.执行器负责具体执行&#xff0c;会调用存储引擎的接口&#xff0c;通过主键索引树搜索获取 id 1 这一行记录&#…

Windows 环境下 Apache 配置 WebSocket 支持

目录 前言1. 基本知识2. 实战前言 🤟 找工作,来万码优才:👉 #小程序://万码优才/r6rqmzDaXpYkJZF 爬虫神器,无代码爬取,就来:bright.cn 原先写过apache的http配置:Apache httpd-vhosts.conf 配置详解(附Demo) 1. 基本知识 🔁 WebSocket 是 HTTP 的升级协议 客户…

UMAEA论文阅读

Preliminaries MMKG为一个五元组G{E, R, A, V, T}&#xff0c;其中E、R、A和V分别表示实体集、关系集、属性集和图像集。 T⊆ERE是关系三元组集。 给定两个MMKG G1 {E1, R1, A1, V1, T1} 和 G2 {E2, R2, A2, V2, T2}&#xff0c; MMEA旨在识别每个实体对&#xff08;e1…

AIGC-十款知识付费类智能体完整指令直接用(DeepSeek,豆包,千问,Kimi,GPT)

Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总游戏脚本-辅助自动化Android控件全解手册再战Android系列Scratch编程案例软考全系列Unity3D学习专栏蓝桥系列AIGC(GPT、DeepSeek、豆包、千问、Kimi)👉关于作者 专注于Android/Unity和各种游戏开发技巧,以及各种资…

Qt界面卡住变慢的解决方法

本质原因: 当Qt界面出现卡顿或无响应时&#xff0c;通常是因为主线程&#xff08;GUI线程&#xff09;被耗时操作阻塞。 完全忘了。。。 Qt Creater解决方法 1. 定位耗时操作 目标&#xff1a;找到阻塞主线程的代码段。 方法&#xff1a; 使用QElapsedTimer测量代码执行时间…

【LangChain4j快速入门】5分钟用Java玩转GPT-4o-mini,Spring Boot整合实战!| 附源码

【LangChain4j快速入门】5分钟用Java玩转GPT-4o-mini&#xff0c;Spring Boot整合实战&#xff01; 前言&#xff1a;当Java遇上大模型 在AI浪潮席卷全球的今天&#xff0c;Java开发者如何快速拥抱大语言模型&#xff1f;LangChain4j作为专为Java打造的AI开发框架&#xff0c…

Vue 3 reactive 和 ref 区别及 失去响应性问题

在 Vue 3 中&#xff0c;reactive 和 ref 是实现响应式数据的两个核心 API&#xff0c;它们的设计目标和使用场景有所不同。以下是两者的详细对比&#xff1a; 1. 基本定义与核心功能 特性reactiveref作用创建对象类型的响应式代理&#xff08;对象、数组、Map 等&#xff09…

第一节:Vben Admin 最新 v5.0初体验

系列文章目录 基础篇 第一节&#xff1a;Vben Admin介绍和初次运行 第二节&#xff1a;Vben Admin 登录逻辑梳理和对接后端准备 第三节&#xff1a;Vben Admin登录对接后端login接口 第四节&#xff1a;Vben Admin登录对接后端getUserInfo接口 第五节&#xff1a;Vben Admin权…

Nginx部署spa单页面的小bug

没部署过&#xff0c;都是给后端干的&#xff0c;自己尝试部署了一个下午终于成功了 我遇到的最大的bug是进入后只有首页正常显示 其他页面全是404&#xff0c;于是问问问才知道&#xff0c;需要这个 location / { try_files $uri $uri/ /index.html; } 让…

面试算法高频08-动态规划-01

动态规划 递归知识要点 递归代码模板&#xff1a;提供递归代码的标准形式public void recur(int level, int param) &#xff0c;包含终止条件&#xff08;if (level> MAX_LEVEL)&#xff09;、当前层逻辑处理&#xff08;process(level, param)&#xff09;、向下一层递归…

若依框架前后端分离版部署全流程详解(本地+服务器+高级配置)

若依框架前后端分离版部署全流程详解&#xff08;本地服务器高级配置&#xff09; 若依&#xff08;RuoYi&#xff09;作为一款基于SpringBoot和Vue的权限管理系统&#xff0c;凭借其模块化设计和开箱即用的特性广受开发者欢迎。本文将从本地部署、服务器部署、高级配置三个维…

医疗设备预测性维护合规架构:从法规遵循到技术实现的深度解析

在医疗行业数字化转型加速推进的当下&#xff0c;医疗设备预测性维护已成为提升设备可用性、保障医疗安全的核心技术。然而&#xff0c;该技术的有效落地必须建立在严格的合规框架之上。医疗设备直接关乎患者生命健康&#xff0c;其维护过程涉及医疗法规、数据安全、质量管控等…

LLMs基础学习(七)DeepSeek专题(4)

LLMs基础学习&#xff08;七&#xff09;DeepSeek专题&#xff08;4&#xff09; 文章目录 LLMs基础学习&#xff08;七&#xff09;DeepSeek专题&#xff08;4&#xff09;DeepSeek-R1 训练过程的四个阶段具体流程小结 “规则化奖励”具体原因小结 “自我认知”&#xff08;se…

SQL 速查手册

前言&#xff1a;SQL&#xff08;Structured Query Language&#xff09;是用于管理关系型数据库的标准语言&#xff0c;广泛应用于数据查询、更新、定义和管理等操作。本文将为你提供一份详细的 SQL 速查手册&#xff0c;涵盖从基础到高级的各种 SQL 操作&#xff0c;帮助你快…

IDEA 中 Scala 项目远程连接虚拟机 Spark 环境

IDEA 中 Scala 项目远程连接虚拟机 Spark 环境 1. 环境准备 确保虚拟机 Spark 环境正常运行 虚拟机中已安装并启动 Spark记录虚拟机的 IP 地址和 Spark 端口&#xff08;默认 7077&#xff09;确保虚拟机防火墙允许相关端口访问 本地 IDEA 环境配置 安装 Scala 插件安装 Spar…

.net core 项目快速接入Coze智能体-开箱即用-全局说明

目录 一、Coze智能体的核心价值 二、开箱即用-效果如下 三 流程与交互设计 为什么要分析意图&#xff0c;而不是全部交由AI处理。 四 接入前的准备工作 五&#xff1a;代码实现----字节Coze 签署 JWT和获取Token .net core 项目快速接入Coze智能体-开箱即用 .net core快…