嵌入式 线程同步的时候pthread_cond_t要和pthread_mutex_t搭配使用

2024-01-05 12:18

本文主要是介绍嵌入式 线程同步的时候pthread_cond_t要和pthread_mutex_t搭配使用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1、互斥锁和条件变量合作示例

pthread_mutex_t count_lock;
pthread_cond_t count_nonzero;
unsigned count = 0;

decrement_count () {
    pthread_mutex_lock (&count_lock);
    while(count==0)
        pthread_cond_wait( &count_nonzero, &count_lock);

    count=count -1;
    pthread_mutex_unlock (&count_lock);
}
 
increment_count(){
    pthread_mutex_lock(&count_lock);
 
    if(count==0)
        pthread_cond_signal(&count_nonzero);
 
    count=count+1;
    pthread_mutex_unlock(&count_lock);
}

decrement_count和increment_count在两个线程A和B中被调用。
正确的情况下,如果decrement_count首先运行,那么A会被阻塞到pthread_cond_wait。随后increment_count运行,它调用pthread_cond_signal唤醒等待条件锁count_nonzero的A线程,但是A线程并不会马上执行,因为它得不到互斥锁count_lock。当B线程执行pthread_mutex_unlock之后A线程才得以继续执行。
 
如果pthread_cond_signal前后没有使用互斥锁count_lock保护,可能的情况是这样。A阻塞到pthread_cond_wait,然后B执行到pthread_cond_signal时候,发生了线程切换,于是A被唤醒,并且发现count依然是0,所以继续阻塞到条件锁count_nonzero上。然后B继续执行,这时候尽管count=1,A永远不会被唤醒了。这样就发生了逻辑错误。
 
当然在这个上下文中,如果把count=count+1放在函数放在pthread_cond_signal之前变成
 
increment_count(){
     count=count+1;
 
    if(count==0)
        pthread_cond_signal(&count_nonzero);
}
 
这样没有问题。但是这种方法并不能保证所有情况下都适用。于是需要用互斥锁保护条件锁相关的变量。也就是说条件锁是用来线程通讯的,但是互斥锁是为了保护这种通讯不会产生逻辑错误,可以正常工作。

条件变量pthread_cond_t怎么用: 

#include <pthread.h> 
#include <stdio.h> 
#include <stdlib.h> 
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;/*初始化互斥锁*/ 
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;/*初始化条件变量*/ 
void *thread1(void *); 
void *thread2(void *); 
int i=1; 
int main(void) 

pthread_t t_a; 
pthread_t t_b; 
pthread_create(&t_a,NULL,thread1,(void *)NULL);/*创建进程t_a*/ 
pthread_create(&t_b,NULL,thread2,(void *)NULL); /*创建进程t_b*/ 
pthread_join(t_a, NULL);/*等待进程t_a结束*/ 
pthread_join(t_b, NULL);/*等待进程t_b结束*/ 
pthread_mutex_destroy(&mutex); 
pthread_cond_destroy(&cond); 
exit(0); 

void *thread1(void *junk) 

for(i=1;i<=6;i++) 

pthread_mutex_lock(&mutex);/*锁住互斥量*/ 
printf("thread1: lock %d/n", __LINE__); 
if(i%3==0){ 
printf("thread1:signal 1 %d/n", __LINE__); 
pthread_cond_signal(&cond);/*条件改变,发送信号,通知t_b进程*/ 
printf("thread1:signal 2 %d/n", __LINE__); 
sleep(1); 

pthread_mutex_unlock(&mutex);/*解锁互斥量*/ 
printf("thread1: unlock %d/n/n", __LINE__); 
sleep(1); 


void *thread2(void *junk) 

while(i<6) 

pthread_mutex_lock(&mutex); 
printf("thread2: lock %d/n", __LINE__); 
if(i%3!=0){ 
printf("thread2: wait 1 %d/n", __LINE__); 
pthread_cond_wait(&cond,&mutex);/*解锁mutex,并等待cond改变*/ 
printf("thread2: wait 2 %d/n", __LINE__); 

pthread_mutex_unlock(&mutex); 
printf("thread2: unlock %d/n/n", __LINE__); 
sleep(1); 


编译: 
[X61@horizon threads]$ gcc thread_cond.c -lpthread -o tcd 
以下是程序运行结果: 
[X61@horizon threads]$ ./tcd 
thread1: lock 30 
thread1: unlock 40 

thread2: lock 52 
thread2: wait 1 55 
thread1: lock 30 
thread1: unlock 40 

thread1: lock 30 
thread1:signal 1 33 
thread1:signal 2 35 
thread1: unlock 40 

thread2: wait 2 57 
thread2: unlock 61 

thread1: lock 30 
thread1: unlock 40 

thread2: lock 52 
thread2: wait 1 55 
thread1: lock 30 
thread1: unlock 40 

thread1: lock 30 
thread1:signal 1 33 
thread1:signal 2 35 
thread1: unlock 40 

thread2: wait 2 57 
thread2: unlock 61 
这里的两个关键函数就在pthread_cond_wait和pthread_cond_signal函数。 
本例中: 

线程一先执行,获得mutex锁,打印,然后释放mutex锁,然后阻塞自己1秒。 

线程二此时和线程一应该是并发的执行 ,这里是一个要点,为什么说是线程此时是并发的执行,因为此时不做任何干涉的话,是没有办法确定是线程一先获得执行还是线程二先获得执行,到底那个线程先获得执行,取决于操作系统的调度,想刻意的让线程2先执行,可以让线程2一出来,先sleep一秒。 
这里并发执行的情况是,线程一先进入循环,然后获得锁,此时估计线程二执行,阻塞在 
pthread_mutex_lock(&mutex); 
这行语句中,直到线程1释放mutex锁 
pthread_mutex_unlock(&mutex);/*解锁互斥量*/ 
然后线程二得已执行,获取metux锁,满足if条件,到pthread_cond_wait (&cond,&mutex);/*等待*/ 
这里的线程二阻塞,不仅仅是等待cond变量发生改变,同时释放mutex锁 ,因为当时看书没有注意,所以这里卡了很久。 
mutex锁释放后,线程1终于获得了mutex锁,得已继续运行,当线程1的if(i%3==0)的条件满足后,通过pthread_cond_signal发送信号,告诉等待cond的变量的线程(这个情景中是线程二),cond条件变量已经发生了改变。 
不过此时线程二并没有立即得到运行 ,因为线程二还在等待mutex锁的释放,所以线程一继续往下走,直到线程一释放mutex锁,线程二才能停止等待,打印语句,然后往下走通过pthread_mutex_unlock(&mutex)释放mutex锁,进入下一个循环。 

这篇关于嵌入式 线程同步的时候pthread_cond_t要和pthread_mutex_t搭配使用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/572838

相关文章

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

服务器集群同步时间手记

1.时间服务器配置(必须root用户) (1)检查ntp是否安装 [root@node1 桌面]# rpm -qa|grep ntpntp-4.2.6p5-10.el6.centos.x86_64fontpackages-filesystem-1.41-1.1.el6.noarchntpdate-4.2.6p5-10.el6.centos.x86_64 (2)修改ntp配置文件 [r

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数

Makefile简明使用教程

文章目录 规则makefile文件的基本语法:加在命令前的特殊符号:.PHONY伪目标: Makefilev1 直观写法v2 加上中间过程v3 伪目标v4 变量 make 选项-f-n-C Make 是一种流行的构建工具,常用于将源代码转换成可执行文件或者其他形式的输出文件(如库文件、文档等)。Make 可以自动化地执行编译、链接等一系列操作。 规则 makefile文件

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

pdfmake生成pdf的使用

实际项目中有时会有根据填写的表单数据或者其他格式的数据,将数据自动填充到pdf文件中根据固定模板生成pdf文件的需求 文章目录 利用pdfmake生成pdf文件1.下载安装pdfmake第三方包2.封装生成pdf文件的共用配置3.生成pdf文件的文件模板内容4.调用方法生成pdf 利用pdfmake生成pdf文件 1.下载安装pdfmake第三方包 npm i pdfma

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]