POSIX编程之互斥和条件变量

Linux程序设计-使用POSIX线程进行多线程编程 在Linux环境下,POSIX线程(POSIX Threads,简称pthread)是一种常用的多线程编程模型。我们学习了如何创建线程、使用互斥锁保护共享资源,以及使用条件变量实现线程之间的同步和通信。POSIX线程是一种轻量级的并发编程机制,它允许程序在同一个进程中同时执行多个独立的线程。每个线程都有自己的执行流程,但共享进程的资源,如内存空间和文件描述符。POSIX线程提供了互斥锁(mutex)和条件变量(condition variable)等机制,用于实现线程之间的协调和同步。 阅读详情

前言


在写这边文章之前很长一段时间,几乎关于多线程对共享数据的保护都是使用互斥量加非同步原语sleep实现,导致性能的降低和cpu的利用率降低。
不要使用如下的代码块:

while(true){
	if(!dataAvailable)
	sleep(some_time);
	else
	consumeData();
}

后来发现一些问题: 如果sleep时间过长,会导致读写数据不实时(比如手机控制机器人运动),如果sleep的时间过短,导致任务内核分的时间片过多,导致CPU占用比较多,白白浪费了大量的性能(Q:但阻塞或中断性能这块是否也是cpu分时间片轮询呢?)。
生产代码中线程的等待可分为两种,一种是等待资源的到来(比如一些复用IO,一般是应用态等待内核态可用,select/poll/eppl_wait等);一种是等着临界区可用时读写共享数据。


多线程对共享资源使用互斥量+sleep方式

  • 是否推荐

线程I生产数据,线程II消费数据。

/*使用该接口替代sleep,原因为sleep的精度不高(涉及到調度延遲),因为设计进程调用等原因
	我們稱爲該接口為優化后的定時器<<UNIX網絡變成卷1>> 6.3 P129
*/
void milliseconds_sleep(int mSec)
{
    struct timeval tv;
    tv.tv_sec=mSec/1000;
    tv.tv_usec=(mSec%1000)*1000;
    int err;
    do{
       err=select(0,NULL,NULL,NULL,&tv);
    }while(err<0 && errno==EINTR);
}
//线程I
while(ture)
{
	pthread_mutex_lock(&mutex);
	//写 共享数据区
	pthread_mutex_unlock(&mutex);
	
	milliseconds_sleep(40);
}
线程II:
while(ture)
{
	pthread_mutex_lock(&mutex);
	//读 共享数据区
	pthread_mutex_unlock(&mutex);
	
	milliseconds_sleep(40);
}

互斥加条件变量(c实现)

线程I(生产者)
pthread_cond_signal(&cond);表示对共享区写数据(布尔值,比如判断共享区缓存的数量,布尔值改变了),触发软中断

while(true == is_run )
{
	pthread_mutex_lock(&lock);
	//对共享区写数据,改变布尔值,改变的时候通常用mutex保护
	do somethings ...
	pthread_mutex_unlock(&lock);
	pthread_cond_signal(&cond);
}

线程II(消费者)
该端为wait端,条件变量只有一种正确使用方式:
1)必须与mutex一起使用,该布尔表达式的读写 需此mutex保护。
2)在mutex已上锁的时候才能调用wait();
3)把判断布尔条件和wait()放到while循环中,不能使用if去判断。

while(true = =is_run)
{
	pthread_mutex_lock(&lock);//满足2)
	while(!ringbuf.size())	//满足3)
	{	
		pthread_cond_wait(&cond, &lock); //满足1)
	}
	if(false == is_run)
	{
		pthread_mutex_unlock(&lock);
		break;
	}
	//读共享区数据,例如链表,队列等
	do somethings...
	pthread_mutex_unlock(&lock);
}

互斥加条件(C++实现)

使用:

#ifndef FUNC_H__
#define FUNC_H__

#include <thread>
#include <vector>
#include "muduo/base/Mutex.h"
#include "muduo/base/Condition.h"

#include "muduo/base/Thread.h"
#include "muduo/base/Types.h"


using namespace muduo;
class CCaptureMgr
{
public:
	typedef struct TagCapture
	{
		char *data;
		size_t	siz;
	}CAPTURE_S;

//	enum {MEMERY_TYPE = 0, FILE_FD_TYPE = 1, CPLUSPLUS_THREAD_TYPE = 2 };
	

	static CCaptureMgr *inst(){static CCaptureMgr cm; return &cm;}

	 int start();
	 int restart();
	 int stop();
	
protected:
	int deleteSource(std::thread *);
	int deleteSource(std::vector<CAPTURE_S> &);

	void pushProc();
	void popProc();

	int put(const CAPTURE_S &);
	int take();

private:
	CCaptureMgr();
	~CCaptureMgr();

	mutable MutexLock mutex_ ;
	Condition cond_ GUARDED_BY(mutex_);
	
	

	std::thread *pPushHandle_;
	std::thread *pPopHandle_;

	bool bRun_;

	std::vector<CAPTURE_S> captureDataList_;
};



#endif


#include <unistd.h>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "function.hpp"




CCaptureMgr::CCaptureMgr():pPushHandle_(nullptr), pPopHandle_(nullptr),bRun_(true),
			mutex_(), cond_(mutex_)
{}

CCaptureMgr::~CCaptureMgr()
{}


int CCaptureMgr::put(const CAPTURE_S &hs_)
{
	MutexLockGuard lock(mutex_);
	//if(hs_.data && hs_.siz)
	{
		captureDataList_.push_back(hs_);
		cond_.notify();
	}
}

int CCaptureMgr::take()
{
	MutexLockGuard lock(mutex_);
	while(captureDataList_.empty())
	{
		cond_.wait();
	}
	std::cout << "siz: " << captureDataList_.size() << std::endl;
	
}


void CCaptureMgr::pushProc()
{
	while(bRun_)
	{
		static int recore = 0;
		CAPTURE_S capture;
		memset(&capture, 0, sizeof(capture));
		capture.data = (char *)calloc(1, 1024);
		capture.siz = strlen(capture.data);
		put(capture);
		sleep(1);
		
		
	}
}

void CCaptureMgr::popProc()
{
	while(bRun_)
	{
		take();
		
	}
}

int CCaptureMgr::start()
{
	int ret = 0;


	if(nullptr == pPopHandle_)
	{
		pPopHandle_ = new std::thread(&CCaptureMgr::popProc, this);
		if(!pPopHandle_)
		{
			std::cout << "创建POP线程失败! " << std::endl;
		}
	}

	if(nullptr == pPushHandle_)
	{
		pPushHandle_ = new std::thread(&CCaptureMgr::pushProc, this);
		if(!pPushHandle_)
		{
			std::cout << "创建PUSH线程失败! " << std::endl;
		}
	}

	return 0;
}

int CCaptureMgr::restart()
{
	stop();
	start();
}

int CCaptureMgr::deleteSource(std::thread *p)
{
	if(p)
	{
		p->join(); delete p; p = 0;
	}
}
int CCaptureMgr::deleteSource(std::vector<CAPTURE_S> &hs_)
{
	if(hs_.size())
	{
		auto it = hs_.begin();
		for(it; it != hs_.end(); ++it)
		{
			if(it->data)
			{
				free(it->data); it->data = 0;
			}
		}
	}
}
int CCaptureMgr::stop()
{
	deleteSource(pPushHandle_);
	deleteSource(pPopHandle_);

	return 0;
}










JavaScript 书签脚本实战:腾讯/优酷/爱奇艺等5大视频站m3u8链接一键提取 本文详细介绍了如何使用JavaScript书签脚本一键提取腾讯视频、优酷、爱奇艺等五大视频平台的m3u8流媒体链接。通过分析播放器内部对象结构,开发者可以高效获取视频源文件,避免录屏画质损失。文章包含各平台适配方案、实战增强功能开发及企业级解决方案设计,帮助用户快速掌握这一实用技术。 阅读详情

相关推荐

UART全功能测试指南:环路/DMA/RS485/硬件流控实战

UART(通用异步收发器)是嵌入式系统中最基础的串行通信接口,其核心原理基于起始位、数据位、校验位与停止位的异步帧结构,依赖精确的波特率时钟同步与采样重建机制。在工业与物联网场景中,UART不仅需保障基本通信可靠性,更需支持DMA卸载、RS485半双工自动方向控制、RTS/CTS硬件流控等进阶能力,以提升实时性、抗干扰性与系统资源效率。典型应用涵盖调试日志输出、传感器数据采集、Modbus RTU总线通信及固件空中升级。本指南聚焦UART外设测试实践,覆盖环路自检、DMA吞吐验证、RS485时序对齐、硬件流

weixin_42599908的博客 133

POSIX 条件变量

目录 基本理解 代码实现 逻辑分析 基本理解 条件变量是用于线程同步,关注对象是共享数据状态的变化,用来协调各个线程合作完成某个任务。当一个动作需要另外一个动作完成时才能进行时,即:当一个线程的行为依赖于另外一个线程对共享数据状态的改变时,这时候就可以使用条件变量。 条件变量是与互斥量相关联的一种用于多线程之间关于共享数据状态改变的通信机制。 条件变量与互斥量一起使用的时候,允许线程以无竞争的方式等待特定的条件发生。 条件变量是由互斥量保护的,线程在改变条件变量状态前必须先锁住互斥量。

动感超人_Crush 515

数据结构——滑动窗口

入:下标为 i 的元素进入窗口,更新相关统计量。如果 i < k−1 则重复第一步更新:更新答案。一般是更新最大值 / 最小值出:下标为 i−k+1 的元素离开窗口,更新相关统计量✔1. 定长子串中元音的最大数目✔2. 找到一个数字的 K 美丽值✔4. 子数组的最大平均数 |方法一:前缀和方法二:滑动窗口7. 得到 K 个黑块的最少涂色次数8. 爱生气的书店老板9. 几乎唯一子数组的最大和10. 长度为 K 子数组中的最大和11. 可获得的最大点数12. 最少交换次数来组合所有的1 ||

qq_68915288的博客 762

Linux-线程同步(条件变量、POSIX信号量)

初始化信号量参数:pshared:0 表示线程间共享,非零表示进程间共享value:信号量初始值,共享资源个数销毁信号量等待信号量//P()功能:等待信号量,会将信号量的值减 1发布信号量//V()功能:发布信号量,表示资源使用完毕,可以归还资源了。将信号量值加 1。张得帅c/Linux基于BlockQueue的生产消费模型基于环形队列的生产消费模型。

m0_74910646的博客 1299

开源DIY龙门架:从零构建可编程运动控制平台

运动控制是自动化与机器人技术的核心基础,它通过精确指令驱动执行机构,实现物体的定位与轨迹规划。其原理通常涉及控制器、驱动器、电机与传动机构的协同工作,核心价值在于将数字指令转化为精准的物理运动,从而解放人力并提升作业一致性。在工业自动化、桌面制造(如3D打印、激光雕刻)及教育机器人等领域应用广泛。本文聚焦于一个具体的工程实践案例:使用**铝型材**、**3D打印**零件、Arduino控制器及步进电机,从机械结构设计、电路连接到代码编写,手把手教你打造一个模块化、可扩展的开源龙门架系统。该系统不仅成本可控,

weixin_33168937的博客 614

R语言层次聚类(hierarchical clustering):数据缩放、PCA聚类结果可视化、fpc包的clusterboot函数通过bootstrap重采样的方法评估hclust层次聚类的稳定性

R语言层次聚类(hierarchical clustering):数据缩放、PCA聚类结果可视化、fpc包的clusterboot函数通过bootstrap重采样的方法评估hclust层次聚类的稳定性

data+scenario+science+insight 833

Linux——线程同步(条件变量、POSIX信号量)和线程池

thrmgr防止线程长期得不到调度的方式也很简单,当线程没有任务时,采用pthread_cond_timedwait函数阻塞等待,该函数第三个参数为设定的timespec时间类型结构体,当检测超时后自动停止阻塞并返回特定值,根据返回值就能判断线程是否是因为超时而停止阻塞,一旦判断超时,线程跳出等待任务的循环然后结束本线程。首先简单说一下什么是循环队列,本质就是长度固定的数组,从头开始插入资源,当插入资源位于最后一个位置的下一个时,再从头开始插入资源,也就是把线性的数组“头尾相连”,变成逻辑上的环形结构。

weixin_61857742的博客 1346

《HiVT: Hierarchical Vector Transformer for Multi-Agent Motion Prediction》论文阅读之HiVT

目录摘要1.介绍2.相关工作3.方法3.1. 总体框架3.2 场景表示 3.3 分层向量Transformer3.3.1 局部编码器3.3.2 全局交互模块3.3.3 多模态未来解码器3.4 训练4.实验4.1 实验设置4.2 消融研究 4.3. 结果5.结论 准确预测周围交通参与者的未来运动对于自动驾驶车辆的安全至关重要。最近,矢量化方法由于能够捕捉交通场景中的复杂交互而在运动预测领域占据主导地位。然而,现有的方法忽略了问题的对称性并且受到昂贵的计算成本的影响,面临着在不牺牲预测性能的情况

Gavinmiaoc的博客 3339

POSIX条件变量

1.什么是条件变量 当一个线程互斥地访问某个变量的时候,它可能发现在其它线程改变状态之前,它什么也做不了 例如一个线程访问队列时,发现对列为空,它只能等待,直到其它线程将一个节点添加到队列中。这种情况就需要条件变量。 2.条件变量函数 pthread_cond_init //初始化 pthread_cond_destroy //销毁 pthread_cond_wait //在一个条件之上等待 pthread_cond_signal //条件满足时向一个等待线程发起通知 pthread_cond_broa

吴刀钓鱼的博客 242

跨境电商产品信息抓取:使用Python爬虫进行市场分析

跨境电商平台是指为不同国家和地区的买卖双方提供在线交易服务的电子商务平台。亚马逊(Amazon):全球最大的电商平台之一,提供丰富的商品种类和全球配送服务。eBay:全球知名的在线拍卖和购物网站,支持个人和企业卖家。速卖通(AliExpress):阿里巴巴旗下的跨境电商平台,主要面向全球消费者提供中国制造的商品。Wish:以移动端为主的跨境电商平台,主打低价商品和个性化推荐。这些平台上的商品数据包括商品名称、价格、销量、用户评价、库存等信息,对于市场分析具有重要价值。

2201_76125261的博客 1231

华为od面试手撕真题【分解质因数】

华为od面试手撕真题【分解质因数】

MISAYAONE的博客 1130

POSIX中的条件变量

在 POSIX 线程(pthreads)模型中,虚假唤醒(spurious wakeup)指的是某个线程在调用pthread_cond_wait()或pthread_cond_timedwait()等待条件变量时,无论是否有其他线程通过pthread_cond_signal()或pthread_cond_broadcast()发出信号,该线程都可能被唤醒并返回——但此时它所等待的“条件”实际上并未成立。while 能在每次假唤醒后重新检查条件,若条件仍不满足,就会再次阻塞,从而有效屏蔽虚假唤醒的干扰;

weixin_43638873的博客 178

2020.12.25丨CRISPResso2安装教程

一个月前接到一个项目,说是做关于CRISPR的编辑效率个性化分析。本来这个分析以前是没有做过的,不过客户发了参考文献。里面流程和命令行都非常清楚,再加上读研期间CRISPR的项目“中道崩殂”,让我对CRiSPR的技术有些执念,便下决心接下来试试。 整个测序分析使用的工具就是CRISPResso,,下面介绍最快捷的安装方式。 首先,CRISPResso只支持python2.X,不支持3.X你需要下载Anaconda或者miniconda,以Miniconda为例: 安装环境: Linux 64-bi

4631

linux网络编程之posix 线程(四):posix 条件变量与互斥锁 示例生产者--消费者问题

一、posix 条件变量 一种线程间同步的情形:线程A需要等某个条件成立才能继续往下执行,现在这个条件不成立,线程A就阻塞等待,而线程B在执行过程中使这个条件成立了,就唤醒线程A继续执行。 在pthread库中通过条件变量(Condition Variable)来阻塞等待一个条件,或者唤醒等待这个条件的线程。Condition Variable用pthread_cond_t类型的变量表

Meditation 7243

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

【Linux应用编程】POSIX线程互斥与同步机制—条件变量

条件变量为什么要和互斥锁一起使用?

只要思想不滑坡,想法总比问题多。 1326

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

并发编程(一): POSIX 使用互斥量和条件变量实现生产者/消费者问题

boost的mutex,condition_variable非常好用。但是在Linux上,boost实际上做的是对pthread_mutex_t和pthread_cond_t的一系列的封装。因此通过对原生态的POSIX 的mutex,cond的生成者,消费者的实现,我们可以再次体会boost带给我们的便利。

anzhsoft的技术专栏 1万+

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

《linux高性能服务器编程》—— 三种线程同步机制的包装类:POSIX信号量、互斥锁和条件变量

(1)POSIX信号量:提供对共享资源的独占式访问 以下使用未命名信号量作为包装类的核心。 #include <semaphore.h> class sem { private: sem_t semp; //信号量 public: sem() { //初始化一个信号量,第2个参数=0则表示此信号量为本进程所有,否则可在多个进程间共享 ...

Keep trying until you get it right 300

Posix多线程编程(1) 互斥锁与条件变量

多线程 互斥锁 以及 条件变量的工作流程

shanki_pm的专栏 875

C++11和POSIX线程库线程互斥与线程同步编程(锁,条件变量,信号量)

文章目录完成两个线程通过条件变量实现交替打印的控制锁+条件变量二元信号量对比一下条件变量和二元信号量按序打印条件变量版二元信号量版生产者消费者条件变量+锁(C++11)多元信号量(有点绕)条件变量和多元信号量的对比 前言:用一些习题来说明这三个东西怎么写。说实话,编写线程同步代码并不简单。 完成两个线程通过条件变量实现交替打印的控制 锁+条件变量 不管是C++11还是POSIX,套路都是一样的 首先要强调的两点: 1.缓冲区队列是临界资源,因此进入就要加锁 2.条件变量是临界资源,进行判断条件是否满足和

m0_51641706的博客 1421

C语言中的POSIX线程与多线程编程:从入门到实践

POSIX 线程(POSIX Threads),简称 pthreads,是 POSIX 标准定义的一套线程接口。它为多线程编程提供了统一的 API,使得程序能够在类 Unix 系统(如 Linux、macOS 等)上创建、管理和同步线程。在 Windows 系统上,也可以通过第三方库(如 pthreads-w32)实现 pthreads 接口。线程PthreadsPOSIX 线程库为 C 语言程序提供了强大的多线程支持,使得程序能够在类 Unix 系统上实现并发和并行处理。

m0_74096349的博客 1135

POSIX多线程笔记(4):互斥量与条件变量

丶未云何龙 353

POSIX 线程详解

作者:Daniel Robbins (drobbins@gentoo.org), 总裁/CEO, Gentoo Technologies, Inc.第一部分:一种支持内存共享的简捷工具POSIX(可移植操作系统接口)线程是提高代码响应和性能的有力手段。在本系列中,Daniel Robbins 向您精确地展示在编程中如何使用线程。其中还涉及大量幕后细节,读完本系列文章,您完全可以运用 POS

菜鸟成长轨迹 4527

Linux Qt使用POSIX多线程条件变量、互斥锁(量)

今天团建,但是文章也要写。酒要喝好,文要写美,方为我辈程序员的全才之路。嘎嘎 之前一直在看POSIX的多线程编程,上个周末结合自己的理解,写了一个基于Qt的用条件变量同步线程的例子。故此来和大家一起分享,希望和大家一起交流。 提到线程,如果在UI编程中,总会和一些耗时操作联系在一起。Qt中处理耗时操作通常有两种方式,一种是将耗时操作放在线程中;另一种则是使用QApplic...

dengsui0790的博客 191

[linux c/c++] 各种锁之间的差异(自旋锁、互斥量、条件变量、屏障、读写锁)

前言: 锁,作为线程间/进程间系统资源,在应对多线程/多进程 访问相同 “资源” 场景时,扮演重要角色。用得好,可以有效地为系统解耦各个模块;但是如果用的不好,一来可能造成系统效率低下( 某条并不重要的流水线长期占据资源锁,另外重要的流水线始终无法获得访问资源的权利 ),二来可能导致系统死锁。 自旋锁: 自旋锁一般用在内核中,其逻辑行为是:“使用cpu反复执行获取锁的动作,直到获取到锁为止”。这里有几个要点: 1)自旋锁如果未获取到锁,则会立刻再次尝试 2)自旋锁的尝试是同步行为,是会占用c.

ykun089的博客 2856

(转贴) Posix线程编程指南(3) 线程同步, 互斥锁pthread_mutex_t , 条件变量pthread_cond_t

 原文出处:http://www.ibm.com/developerworks/cn/linux/thread/posix_threadapi/part3/index.htmldeveloperWorks 中国  >  Linux  >Posix线程编程指南(3)线程同步文档选项<trvalign="top"><img alt="" height="1" width="8"src="//w

Wenxy's computer science technology blog 1761

Posix条件变量:与互斥锁共同解决生产者与消费者关系

#include <unistd.h> #include <sys/types.h> #include <pthread.h> #include <semaphore.h> #include <stdlib.h> #include <stdio.h> #include <errno.h> #include &lt...

qq_22753933的博客 496
上一篇: 社保异地办理
下一篇: netstat工具使用
帘下有白绿
博客等级 码龄12年 165粉丝 44原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值