☰
【Qt】系统相关:多线程-条件变量与信号量
2026/10/12 5:05:03 网站建设 项目流程


🎬 个人主页:艾莉丝努力练剑

❄专栏传送门:《C语言》《数据结构与算法》《C/C++干货分享&学习过程记录》
《Linux操作系统编程详解》《笔试/面试常见算法:从基础到进阶》《Python干货分享》
⭐️为天地立心,为生民立命,为往圣继绝学,为万世开太平

🎬 艾莉丝的简介:


文章目录

  • 1 ~> Qt 多线程:条件变量与信号量
    • 1.1 QWaitCondition 条件变量
      • 1.1.1 核心概念
      • 1.1.2 标准使用范式
        • 等待线程代码示例
        • 唤醒线程代码示例
      • 1.1.3 while 替代 if 的根本原因
      • 1.1.4 关键约束
  • 2 ~> QSemaphore 计数信号量
    • 2.1 核心概念
    • 2.2 核心 API
    • 2.3 使用示例
    • 2.4 QSemaphore 与 QMutex 对比
  • 3 ~> 条件变量 vs 信号量 复习总结
    • 3.1 QWaitCondition(条件变量)
    • 3.2 QSemaphore(计数信号量)
    • 3.3 底层关联性
  • 结尾


1 ~> Qt 多线程:条件变量与信号量

Qt 对 Linux 原生并发原语做面向对象封装,底层逻辑与 Linux 系统条件变量、计数信号量保持一致,简化原生系统 API 的使用复杂度。

1.1 QWaitCondition 条件变量

1.1.1 核心概念

  • 作用:干预多线程执行顺序,实现线程等待‑唤醒同步机制,解决线程间条件等待问题。
  • 本质:对 Linuxpthread_cond_t条件变量的面向对象封装。
  • 配套依赖:必须和QMutex互斥锁协同工作。
  • 核心成员函数
    • wait(QMutex *mutex):线程阻塞等待条件;执行时原子操作:释放互斥锁,进入阻塞;被唤醒后重新获取互斥锁,函数返回。
    • wakeOne():唤醒一个处于等待状态的线程。
    • wakeAll():唤醒全部处于等待状态的线程。

1.1.2 标准使用范式

重点:条件判断必须使用while,禁止使用if,处理虚假唤醒(spurious wakeup)。虚假唤醒指线程在没有收到显式唤醒信号的情况下从 wait 返回,此时条件依然不满足,需要再次进入等待。

等待线程代码示例
QMutex mutex;QWaitCondition condition;// 等待条件的线程mutex.lock();// while循环校验条件,防止虚假唤醒while(!conditionFullfilled()){// 原子操作:释放mutex锁,线程阻塞;被唤醒后重新获取锁再返回condition.wait(&mutex);}// 条件满足,执行业务逻辑// ...mutex.unlock();
唤醒线程代码示例
// 修改条件并唤醒的线程mutex.lock();changeCondition();// 修改同步条件,修改共享状态必须在锁保护内condition.wakeAll();// 唤醒全部等待线程;也可使用wakeOne唤醒单个线程mutex.unlock();

1.1.3 while 替代 if 的根本原因

  1. 系统允许条件变量发生虚假唤醒:线程可以不经 wakeOne/wakeAll 就从 wait 函数返回。
  2. 唤醒之后共享状态可能已经被其他线程修改,条件再次变为不成立。
  3. while会循环重新校验条件,条件不满足继续 wait;if仅做一次判断,虚假唤醒后会直接向下执行,造成逻辑错误。

1.1.4 关键约束

  1. 调用wait()前线程必须已经拿到传入的 QMutex 锁,否则行为未定义。
  2. 修改用于判断的共享条件变量,必须放在互斥锁临界区内,保证线程安全。
  3. wakeOne /wakeAll 调用不强制要求锁持有,但最佳实践:修改条件和唤醒操作都在锁保护区间内完成。

2 ~> QSemaphore 计数信号量

2.1 核心概念

  • 作用:控制有限资源的并发访问,限制同时访问共享资源的线程数量,是计数信号量。
  • 对比 Linux 原生信号量:
    • Linux 信号量:既支持线程间同步,也支持进程间同步(IPC)。
    • QtQSemaphore:仅用于同一进程内部多线程同步,不支持跨进程通信。
  • 本质:内部维护一个资源计数器,代表可用资源数量。

2.2 核心 API

  • 构造函数:QSemaphore(int n),设置初始可用资源计数为 n。
  • acquire():P 操作,资源计数减 1;若当前计数为 0,则线程阻塞等待资源。
  • release(int n = 1):V 操作,资源计数增加 n,唤醒等待的线程。

2.3 使用示例

// 初始化信号量,允许最多2个线程同时访问资源QSemaphoresemaphore(2);// 访问受限资源的线程逻辑semaphore.acquire();// P操作,获取资源;资源耗尽时线程阻塞// 访问有限的共享资源// ...semaphore.release();// V操作,归还资源,计数器+1

2.4 QSemaphore 与 QMutex 对比

  • QMutex:互斥锁,等价于初始值为 1 的信号量,同一时刻只允许一个线程进入临界区。
  • QSemaphore:计数信号量,初始值可以大于 1,支持 N 个线程同时访问资源,用于资源池、限流场景。

3 ~> 条件变量 vs 信号量 复习总结

3.1 QWaitCondition(条件变量)

  • 适用场景:线程等待某个逻辑条件成立才继续运行,生产者‑消费者模型。
  • 依赖:必须绑定互斥锁 QMutex。
  • 关注点:状态条件是否成立。

3.2 QSemaphore(计数信号量)

  • 适用场景:资源数量有限,对并发访问数量做限流控制。
  • 依赖:内部自带计数器,不需要外部互斥锁。
  • 关注点:可用资源的数量。

3.3 底层关联性

Qt 的这两个并发组件均是对 POSIX 线程原语的封装;掌握 Linux 下 pthread 条件变量、POSIX 信号量,即可直接迁移理解 Qt 多线程同步逻辑。


结尾

uu们,本文的内容到这里就全部结束了,艾莉丝在这里再次感谢您的阅读!

艾莉丝努力练剑

C/C++ & Linux 底层探索者 | 一个正在努力练剑的技术博主

👀【关注】跟随我一起深耕技术领域,见证每一次成长。
❤️【点赞】让优质内容被更多人看见,让知识传递更有力量。
⭐【收藏】把核心知识点存好,在需要时随时查、随时用。
💬【评论】分享你的经验或疑问,评论区一起交流避坑!

不要忘记给博主“一键四连”哦!

“今日练剑达成!”

“技术之路难免有困惑,但同行的人会让前进更有方向。”

结语:希望对学习Linux相关内容的uu有所帮助,不要忘记给博主“一键四连”哦!

往期回顾:

【QT】系统相关:QT中的锁

🗡博主在这里放了一只小狗,大家看完了摸摸小狗放松一下吧!🗡
૮₍ ˶ ˊ ᴥ ˋ˶₎ა

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询