pthread_cond_signal 和 pthread_mutex_unlock顺序问题

robot framework循环读取excel表操作 robot framework循环读取excel表操作 1、安装excellibrary,注意python3.7版本,需安装:robotframework-excel,robotframework-excellibrary-xwfintech 注意:网上有很多excel处理的,都是基于python2.7的,还有一些对python3以上都是修改包的方式,其实都不需要,在pip官网上有python3以上的excellibrary,名称是robotframework-excellib 2.0.0,但是该包关键字不 阅读详情

from:http://stackoverflow.com/questions/1640389/pthreads-pthread-cond-signal-from-within-critical-section

Question1:

I have the following piece of code in thread A, which blocks using pthread_cond_wait()


[cpp]  view plain  copy
 print ?
  1. pthread_mutex_lock(&my_lock);       
  2. if ( false == testCondition )          
  3.     pthread_cond_wait(&my_wait,&my_lock);   
  4. pthread_mutex_unlock(&my_lock);  

I have the following piece of code in thread B, which signals thread A

[cpp]  view plain  copy
 print ?
  1. pthread_mutex_lock(&my_lock);    
  2. testCondition = true;  
  3. pthread_cond_signal(&my_wait);  
  4. pthread_mutex_unlock(&my_lock);  

Provided there are no other threads, would it make any difference if pthread_cond_signal(&my_wait) is moved out of the critical section block as shown below ?

[cpp]  view plain  copy
 print ?
  1. pthread_mutex_lock(&my_lock);    
  2. testCondition = true;  
  3. pthread_mutex_unlock(&my_lock);  
  4. pthread_cond_signal(&my_wait);  


Answer1:
My recommendation is typically to keep the pthread_cond_signal() call inside the locked region, but probably not for the reasons you think.

In most cases, it doesn't really matter whether you call pthread_cond_signal() with the lock held or not. Ben is right that some schedulers may force a context switch when the lock is released if there is another thread waiting, so your thread may get switched away before it can call pthread_cond_signal(). On the other hand, some schedulers will run the waiting thread as soon as you call pthread_cond_signal(), so if you call it with the lock held, the waiting thread will wake up and then go right back to sleep (because it's now blocked on the mutex) until the signaling thread unlocks it. The exact behavior is highly implementation-specific and may change between operating system versions, so it isn't anything you can rely on.


But, all of this looks past what should be your primary concern, which is the readability and correctness of your code. You're not likely to see any real-world performance benefit from this kind of micro-optimization (remember the first rule of optimization: profile first, optimize second). However, it's easier to think about the control flow if you know that the set of waiting threads can't change between the point where you set the condition and send the signal. Otherwise, you have to think about things like "what if thread A sets testCondition=TRUE and releases the lock, and then thread B runs and sees that testCondition is true, so it skips the pthread_cond_wait() and goes on to reset testCondition to FALSE, and then finally thread A runs and calls pthread_cond_signal(), which wakes up thread C because thread B wasn't actually waiting, but testCondition isn't true anymore". This is confusing and can lead to hard-to-diagnose race conditions in your code. For that reason, I think it's better to signal with the lock held; that way, you know that setting the condition and sending the signal are atomic with respect to each other.


On a related note, the way you are calling pthread_cond_wait() is incorrect. It's possible (although rare) for pthread_cond_wait() to return without the condition variable actually being signaled, and there are other cases (for example, the race I described above) where a signal could end up awakening a thread even though the condition isn't true. In order to be safe, you need to put the pthread_cond_wait() call inside a while() loop that tests the condition, so that you call back into pthread_cond_wait() if the condition isn't satisfied after you reacquire the lock. In your example it would look like this:

[cpp]  view plain  copy
 print ?
  1. pthread_mutex_lock(&my_lock);       
  2. while ( false == testCondition ) {  
  3.     pthread_cond_wait(&my_wait,&my_lock);  
  4. }  
  5. pthread_mutex_unlock(&my_lock);  


(I also corrected what was probably a typo in your original example, which is the use of my_mutex for the pthread_cond_wait() call instead of my_lock.)


Question2:

为了判断所有线程已经终止而又不用pthread_join,只好又引入另外一个pthread同步对象:条件变量. 
/* current working threads number */ 
static int curnum = 0; 
/* mutex lock for curnum */ 
static pthread_mutex_t mutex_curnum = PTHREAD_MUTEX_INITIALIZER; 
/* cond for curnum */ 
static pthread_cond_t cond_curnum = PTHREAD_COND_INITIALIZER; 

变量curnum代表当前活动线程数,在线程scan函数结尾增加一下代码: 
pthread_mutex_lock(&mutex_curnum); 
if (!--curnum) 
pthread_cond_signal(&cond_curnum); 
pthread_mutex_unlock(&mutex_curnum); 
return NULL; 
每个线程终止时把curnum减1,如果curnum等0,那么通知main所有线程都已 
终止. main在创建完线程后就已以下代码阻塞在cond_curnum上: 
pthread_mutex_lock(&mutex_curnum); 
while(curnum) 
pthread_cond_wait(&cond_curnum,&mutex_curnum); 
pthread_mutex_unlock(&mutex_curnum); 
********************************************

pthread_cond_signal 一定要放在pthread_mutex_unlock之前吗?


Answer2:

pthread_cond_signal()的具体位置?

"pthread_cond_signal()必须要放在pthread_mutex_lock() 和pthread_mutex_unlock() 之间, "
这个做法有个问题,举个例子

简单假设线程1、2,curnum 值为 1, 语句执行顺序如下:
[cpp]  view plain  copy
 print ?
  1.                                                      
  2. T2-->;pthread_mutex_lock(&mutex_curnum);                
  3. T2-->;while(curnum)                                     
  4. T2-->;  pthread_cond_wait(&cond_curnum,&mutex_curnum);/*T2解锁,睡眠,等信号*/  
  5. T1-->;pthread_mutex_lock(&mutex_curnum);              /*轮T1运行,T1上锁*/                                                     
  6. T1-->;if (!--curnum)                                  /*条件成立*/  
  7. T1-->;    pthread_cond_signal(&cond_curnum);          /*T1向线程T2发信号*/  
  8. T2-->;pthread_cond_wait(&cond_curnum,&mutex_curnum);  /*T1时间片用完,换T2执行,但发觉不能上锁,因为T1持有锁*/                                                        
  9. T1-->;pthread_mutex_unlock(&mutex_curnum);            /*T1解锁*/  

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
问题在于一个条件变量和一个互斥锁关联,
一个线程在持有锁的情况下调用pthread_cond_signal(), 
则等待条件的线程有可能得不到锁。

就上面的特定例子来,配合每条语句的执行顺序,
虽然T1调用了pthread_cond_signal(), 但是T2 100%不能获得锁。

《UNIX网络编程第2卷:进程间通信》提了一个改进方法


[cpp]  view plain  copy
 print ?
  1. pthread_mutex_lock();  
  2. 判断是否别个线程等待的条件发生,是的话设 "发生标志" 为 "是";  
  3. pthread_mutex_unlock();   
  4. if (发生标志 == 是)  
  5. {  
  6.     pthread_cond_signal(...);  
  7. }  

例子如下:

shows an example of how to use condition variables and mutexes together to synchronize threads.

The condition is the state of the work queue. We protect the condition with a mutex and evaluate the condition in a while loop. When we put a message on the work queue, we need to hold the mutex, but we don't need to hold the mutex when we signal the waiting threads. As long as it is okay for a thread to pull the message off the queue before we call cond_signal, we can do this after releasing the mutex. Since we check the condition in a while loop, this doesn't present a problem: a thread will wake up, find that the queue is still empty, and go back to waiting again. If the code couldn't tolerate this race, we would need to hold the mutex when we signal the threads.

gure 11.14. Using condition variables
#include <pthread.h>

struct msg {
    struct msg *m_next;
    /* ... more stuff here ... */
};
struct msg *workq;
pthread_cond_t qready = PTHREAD_COND_INITIALIZER;
pthread_mutex_t qlock = PTHREAD_MUTEX_INITIALIZER;

void
process_msg(void)
{
    struct msg *mp;

    for (;;) {
        pthread_mutex_lock(&qlock);
        while (workq == NULL)
            pthread_cond_wait(&qready, &qlock);
        mp = workq;
        workq = mp->m_next;
        pthread_mutex_unlock(&qlock);
        /* now process the message mp */
    }
}

void
enqueue_msg(struct msg *mp)
{
    pthread_mutex_lock(&qlock);
    mp->m_next = workq;
    workq = mp;
    pthread_mutex_unlock(&qlock);
    pthread_cond_signal(&qready);
}


pthread_cond_wait必须放在pthread_mutex_lock和pthread_mutex_unlock之间,因为他要根据共享变量的状态来觉得是否要等待,而为了不永远等待下去所以必须要在lock/unlock队中
共享变量的状态改变必须遵守lock/unlock的规则

pthread_cond_signal即可以放在pthread_mutex_lock和pthread_mutex_unlock之间,也可以放在pthread_mutex_lock和pthread_mutex_unlock之后,但是各有有缺点。

之间:
pthread_mutex_lock
    xxxxxxx
pthread_cond_signal
pthread_mutex_unlock
缺点:在某下线程的实现中,会造成等待线程从内核中唤醒(由于cond_signal)然后又回到内核空间(因为cond_wait返回后会有原子加锁的行为),所以一来一回会有性能的问题。但是在LinuxThreads或者NPTL里面,就不会有这个问题,因为在Linux 线程中,有两个队列,分别是cond_wait队列和mutex_lock队列, cond_signal只是让线程从cond_wait队列移到mutex_lock队列,而不用返回到用户空间,不会有性能的损耗。
所以在Linux中推荐使用这种模式。

之后:
pthread_mutex_lock
    xxxxxxx
pthread_mutex_unlock
pthread_cond_signal
优点:不会出现之前说的那个潜在的性能损耗,因为在signal之前就已经释放锁了
缺点:如果unlock和signal之前,有个低优先级的线程正在mutex上等待的话,那么这个低优先级的线程就会抢占高优先级的线程(cond_wait的线程),而这在上面的放中间的模式下是不会出现的。

所以,在Linux下最好pthread_cond_signal放中间,但从编程规则上说,其他两种都可以
AgentScope Java 2.0 最佳实践:9 个完整示例手把手带你开发 Java‑Agent 本文基于9 个完整示例,深入剖析从基础对话(BasicChatExample)、工具调用(@Tool 注解)、结构化输出(POJO Schema)、ToolGroup 自主管理、MCP 外部工具集成、Hook 生命周期监控、Spring Boot SSE 流式 Web、JsonSession 会话持久化到中断恢复的全链路实战教程。 阅读详情

相关推荐

MATLAB仿真耗散孤子共振与金兹堡-朗道方程解析

耗散孤子共振(DSR)是非线性光学中的特殊脉冲现象,通过平衡非线性效应、色散与能量耗散实现稳定传输。其核心数学模型金兹堡-朗道方程(GLE)描述了光脉冲在增益介质中的演化规律,采用分步傅里叶方法(SSFM)可高效求解这类非线性偏微分方程。该技术在光纤激光器设计、高速光通信系统优化等领域具有重要价值,特别是在需要高能量脉冲保持稳定传输的场景。MATLAB数值仿真为理解DSR物理机制提供了直观工具,通过参数扫描可验证脉冲能量与宽度的线性关系特征,并为实际器件设计提供预测依据。

weixin_31240035的博客 257

多线程时需要注意互斥锁的加锁顺序,防止死锁

C/C++多线程编程,需要注意加锁顺序,防止出现死锁

weixin_43354152的博客 1459

GPL vs MIT:独立开发者选择开源协议的法律与商业考量

你可能听过这样的故事:某个开发者用业余时间写了个超好用的工具库,开源后被某大厂悄悄集成到闭源产品里赚得盆满钵满,开发者却连杯奶茶钱都没拿到;也可能听说过另一个案例:开发者选了GPL协议,结果用户修改代码后必须开源,反而推动项目社区快速壮大,最终靠技术服务赚到了钱。这些故事的核心矛盾,都源于开源协议的选择。对于独立开发者(尤其是单枪匹马写代码的个人或小团队),开源协议不是“随便选一个就行”的小事——它是代码的“使用说明书”,更是保护自身权益、规划项目未来的关键工具。

AI天才研究院 1177

[多线程] pthread_cond_signal()和pthread_cond_wait()用法解析

pthread_mutex_t count_lock; //互斥量 pthread_cond_t count_nonzero; //条件变量 unsigned count; /* 线程1 */ decrement_count() { pthread_mutex_lock(&count_lock); while (count == 0) { p...

xl365t 7415

Kaamel白皮书:IoT设备安全隐私评估实践

明确评估的目的和预期结果。

kaamelai的博客 1317

Underactuated Robotics - 欠驱动机器人学(一)- 全驱动与欠驱动系统

根据牛顿的观点,机械系统的动力学是二阶的(其状态由位置向量 q(也称为配置向量)和速度向量以及(可能还有)时间给出。二阶控制动力系统的一般形式是:其中 u 是控制向量。定义 1.1 (欠驱动控制微分方程) 二阶控制微分方程描述如下:在状态和时间 t 中,如果所得到的映射是可射的:对于每一个,都存在一个能产生预期响应的,那么系统就是全驱动的。否则,就是欠驱动(状态在时间 t)。

机器人控制与仿真应用 3377

条件变量signal与unlock的顺序

条件变量signal与unlock的顺序   编写同步队列时,有用到条件变量,对操作队列的线程进行同步。当队列为空时,允许get线程挂起,直到add线程向队列添加元素并通过唤醒条件变量,get线程继续向下运行。条件变量在多线程程序中用来实现“等待->唤醒”逻辑常用的方法。条件变量要和互斥量相联结,以避免出现条件竞争:一个线程预备等待一个条...

weixin_30347009的博客 366

010、Zephyr RTOS开发环境搭建(Docker)

摘要 本文分享了使用Docker搭建Zephyr RTOS开发环境的实践经验。作者通过团队新人配置环境的真实案例,指出传统安装方式存在版本冲突、缓存污染等问题,而Docker方案能确保环境一致性。文章详细介绍了自定义Docker镜像的设计思路,重点解决工具链版本匹配、Python虚拟环境隔离等问题,将镜像体积从2GB优化到800MB。提供了从拉取镜像到点亮LED的完整工作流程,并总结了USB设备直通、文件权限、缓存问题等常见陷阱。还探讨了多阶段构建、CI集成等进阶用法,同时客观分析了Docker方案的局限性

m0_50546716的博客 78

条件变量用例--解锁与signal的顺序问题

我们知道,当调用signal/broadcast唤醒等待条件变量的其他线程时,既可以在加锁的情况下调用signal/broadcast,也可以在解锁的情况下调用。 那么,到底哪种情况更好呢?man手册中其实已经给出了答案: The pthread_cond_broadcast() or pthread_cond_signal() funct...

weixin_30374009的博客 799

第16课:动手实战中文句法依存分析

句法分析是自然语言处理(NLP)中的关键技术之一,其基本任务是确定句子的句法结构或者句子中词汇之间的依存关系。主要包括两方面的内容:一是确定语言的语法体系,即对语言中合法句子的语法结构给予形式化的定义;另一方面是句法分析技术,即根据给定的语法体系,自动推导出句子的句法结构,分析句子所包含的句法单位和这些句法单位之间的关系。 句法分析被用在很多场景中,比如搜索引擎用户日志分析和关键词识别,比如信息抽...

春华秋实 2435

【华为OD机试真题】29、组成最大数 | 机试真题+思路参考+代码解析 (C++、Java、Py、C语言、JS)

题目描述 >小组中每位都有一张卡片,卡片上是6位内的正整数,将卡片连起来可以组成多种数字,计算组成的最大数字

KJ.JK 2418

POSIX线程-条件变量(二)

pthread_cond_signal()和pthread_cond_wait()的典型使用方法 pthread_mutex_t mtx; pthread_cond_t cond; 线程A中通知的执行的操作 s = pthread_mutex_lock(&mtx) if (s != 0) err_exit(); a++;/*谓词条件*/ …… do s

huangyimo的专栏 895

S7-1500 PLC与多台S7-200SMART PLC进行PROFINET通信的快捷方法

S7-1500 PLC与多台S7-200SMART PLC进行PROFINET通信的快捷方法

Robot_PLC_HMI_Automation 5686

pthread_cond_signal该放在什么地方?

pthread_cond_signal()的具体位置? "pthread_cond_signal()必须要放在pthread_mutex_lock() 和pthread_mutex_unlock() 之间, " 我认为这个做法有个问题,举个例子 简单假设线程1、2,curnum 值为 1, 语句执行顺序如下: ...

weixin_33979745的博客 321

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

【Linux】二十八.线程篇五《Linux多线程编程:线程同步之条件变量》---详解

在上节内容中我们学习了线程篇五,这节内容我们详细讲解线程同步.

2501_93351213的博客 571

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

Linux线程互斥锁原理与实战:从pthread_mutex到死锁预防

在多线程编程中,线程同步是确保数据一致性的核心技术,其核心原理是通过互斥机制防止多个线程同时访问共享资源。Linux系统通过pthread_mutex_t等同步原语实现这一机制,底层依赖futex(快速用户态互斥锁)等高效内核协作,在用户态进行锁竞争,仅在必要时陷入内核,大幅降低系统开销。线程互斥锁的技术价值在于保障高并发程序的正确性与性能,广泛应用于网络服务器、数据库连接池、高性能计算等场景。本文聚焦pthread_mutex的底层实现、使用模式及死锁预防,结合原子操作与条件变量等热词,深入解析Linux

weixin_30619101的博客 401

老版QQ原生表情gif动态

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

Linux系统编程——线程pthread初探

目录:1.引入:2.概要:3.线程:4.互斥锁:5.条件变量: 1.引入: 典型的UNIX/Linux进程可以看成只有一个控制线程:一个进程在同一时刻只做一件事情。有了多个控制线程后,在程序设计时可以把进程设计成在同一时刻做不止一件事,每个线程各自处理独立的任务。 进程是程序执行时的一个实例,是担当分配系统资源(CPU时间、内存等)的基本单位。在面向线程设计的系统中,进程本身不是基本运行单位,而是线程的容器。程序本身只是指令、数据及其组织形式的描述,进程才是程序(那些指令和数据)的真正运行实例。

莘莘的博客 1764

Linux线程4.0-线程同步-条件变量cond,深入生产者-消费者模型。

摘要:本文探讨了多线程编程中因线程不同步导致的CPU资源分配不均问题。当单线程过度占用CPU时,其他线程会出现"饥饿"现象。解决方法包括使用条件变量和POSIX信号量进行线程同步控制。条件变量允许线程在条件不满足时休眠等待,并在适当时机被唤醒。文中详细介绍了条件变量的初始化、等待、唤醒及销毁操作,并通过生产者-消费者模型展示了阻塞队列的实现方法。重点强调了在多线程环境下保证原子操作的加锁/解锁机制,以及线程间通信的设计要点。

深入探究的博客 547

Linux Pthread多线程编程:从基础概念到线程安全队列实战

多线程编程是现代软件开发中提升程序并发性能的核心技术,它允许程序同时执行多个任务,充分利用多核CPU的计算能力。其基本原理是通过创建多个独立的执行流(线程),共享进程的内存空间,从而实现数据的高效共享与通信。在Linux环境下,POSIX线程(Pthread)是实现多线程编程的C语言标准库,它提供了线程创建、同步、销毁等底层原语,是构建高性能服务器、并行计算和实时系统的技术基石。理解Pthread的互斥锁(mutex)和条件变量(cond)等同步机制,对于避免数据竞争和死锁至关重要,这直接关系到程序的正确性

weixin_34021089的博客 340

互斥和同步(生产者消费者模型)

注:该类型的生产者消费者模型将缓冲区当作局部使用(但也不是完全局部,至少没有实现生产者之间的并发(并行)放入,只实现了生产者和消费者之间的并发(并行)访问)。被挂起的执行流的PCB/TCB会被放到内核中的某等待队列中,并且PCB/TCB的状态会被修改为睡眠,所以本执行流不再被调度。对条件变量进一步的叙述需要结合接口的使用来进行,所以在这里先来介绍一下条件变量接口的使用,希望读者不要感到突兀。当然,互斥的实现方式多种多样,比如中断屏蔽,比如OS提供的原子操作接口,而我给读者介绍的只是其中一种——互斥锁。

2302_80221042的博客 831

17_线程互斥量和信号量的使用

摘要:本文介绍了线程同步中信号量和互斥量的使用机制。重点分析了pthread_cond_wait的线程状态变化:先释放互斥锁进入阻塞状态,收到信号后变为就绪状态,必须重新获取互斥锁才能继续执行。通过生产者-消费者模型示例,说明了条件变量和互斥锁的配合使用方式。同时指出,pthread_cond_signal应在解锁前调用,以避免竞态条件和减少线程切换开销。这种顺序能确保被唤醒线程在锁释放后立即获取锁,提高同步效率。

qq_40681630的博客 753

pthread_cond_wait

考虑下面两种情况: Example 1 thread 1:     pthread_mutex_lock(&mutex);     while (!condition)         pthread_cond_wait(&cond, &mutex);     /* do something that requires holding the mutex and conditi

278

Linux的锁和条件变量用法 | pthread_mutex_lock | pthread_cond_signal

原文地址:  http://hi.baidu.com/hehehehello/item/01e65ec5e3a46909c710b244 本篇默认读者已经清楚多线程中的锁、互斥锁、条件变量基本概念及作用,本篇只讲怎么在C++里编程调用。互斥锁很简单,条件变量(多用于生产者-消费者模型)则细节较多,本文主要说它。 主要涉及函数 #includepthread

Crazy Tortoise 1729

探究 “条件变量signal时是否需要持有mutex”

Waiting Process pthread_mutex_lock(&amp;amp;amp;amp;amp;amp;amp;mutex); while (condition == FALSE) pthread_cond_wait(&amp;amp;amp;amp;amp;amp;amp;cond, &amp;amp;amp;amp;amp;amp;amp;mutex); pthread_mutex_unlock(&amp;amp;amp;amp;amp;a

rsy56640的博客 779

线程同步与互斥 [ 中 ]

文章摘要:本文深入探讨了线程同步与互斥的实现原理及应用场景。首先分析了纯互斥机制带来的线程饥饿问题,指出同步技术是解决低效和不公平问题的关键。通过生产者-消费者模型的具体示例,详细讲解了条件变量的工作原理及其API使用方式,包括pthread_cond_wait、pthread_cond_signal等核心函数的原子操作特性。文章还实现了基于阻塞队列的生产者消费者模型,展示了如何通过互斥锁和条件变量实现线程间的安全协作。最后扩展到多生产多消费场景,验证了该模型的高效性。全文通过代码实例和理论分析相结合的方式

Small_entreprene的博客 1150

【学习笔记】天嵌2440第三季下学期——linux多线程同步

实现线程同步可以通过低级的编程手段实现: 上代码: #include #include pthread_t thread[2]; int number = 0; pthread_mutex_t mut; void studentA() { int i; for (int i = 0; i < 5; i++) { //扫一次地 printf("swaping%d\n",

tinnu的博客 365
上一篇: QtXlsx读写.xlsx的图片
下一篇: Qt读取中文文本,兼容GBK&&UTF-8
鱼公子哟西
博客等级 码龄14年 17粉丝 24原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值