在多线程开发中,经常需要控制多个线程对共享资源的访问数量。例如限制同时下载文件的数量、控制数据库连接池的连接使用等等。这时候,Qt 提供的 QSemaphore
(信号量)就非常派得上用场。
一、什么是 QSemaphore?
QSemaphore
是 Qt 中提供的一种线程同步工具。它通过内部维护一个资源计数器,允许多个线程同时访问共享资源,但访问数量受到限制。
它与互斥锁(QMutex
)的区别在于:
QMutex
是互斥的,每次只允许一个线程进入临界区。QSemaphore
是限量的,可以允许多个线程同时访问资源,但不会超过指定的最大数量。
可以把 QSemaphore
想象成一个“通行证发放器”:资源有限,有票的线程才能进入,无票的线程就只能等着。
二、典型应用场景
- 同时最多只允许 N 个线程运行某项任务(例如下载器中最多允许 3 个并发下载)
- 限制线程池中可用线程的最大数
- 实现生产者-消费者模式中的缓冲区容量限制
- 控制数据库连接池的并发访问数量
总之,任何需要限制并发访问数量的场景,QSemaphore
都能派上用场。
三、常用方法说明
方法名 | 说明 |
---|---|
acquire(int n = 1) | 申请 n 个资源,不足则阻塞线程,直到资源可用 |
release(int n = 1) | 释放 n 个资源,通知其他等待的线程 |
tryAcquire(int n = 1) | 尝试申请 n 个资源,如果资源不足,立即返回 false |
available() | 获取当前可用的资源数量 |
四、实战案例:限制同时运行线程数
目标说明
创建 10 个线程,每个线程执行一项任务。但系统最多只允许 3 个线程同时执行,其余线程必须等待已有线程完成任务后再开始执行。
C++ 代码示例(基于 Qt)
#include <QCoreApplication>
#include <QThread>
#include <QSemaphore>
#include <QDebug>// 最大并发线程数设为 3
const int MAX_CONCURRENT = 3;
QSemaphore semaphore(MAX_CONCURRENT);// 自定义线程类
class Worker : public QThread
{int id;public:Worker(int id) : id(id) {}void run() override {// 申请资源,如果不足会阻塞semaphore.acquire();qDebug() << "线程" << id << "开始执行任务...";// 模拟任务耗时QThread::sleep(2);qDebug() << "线程" << id << "任务完成!";// 释放资源semaphore.release();}
};int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);QList<Worker*> workers;// 启动 10 个线程for (int i = 0; i < 10; ++i) {Worker* w = new Worker(i + 1);workers.append(w);w->start();}// 等待所有线程执行完成for (Worker* w : workers) {w->wait();delete w;}qDebug() << "所有任务执行完毕!";return 0;
}
程序输出(示例)
线程1开始执行任务...
线程2开始执行任务...
线程3开始执行任务...
线程1任务完成!
线程4开始执行任务...
线程2任务完成!
线程5开始执行任务...
...
所有任务执行完毕!
可以看到:每次最多只有 3 个线程在执行任务,正是通过 QSemaphore
实现的并发控制。
五、代码讲解
-
QSemaphore semaphore(MAX_CONCURRENT);
初始化信号量对象,设定最大可用资源为 3,表示同时最多有 3 个线程能进入临界区。 -
semaphore.acquire();
当前线程申请一个资源。如果当前资源不足(即已经有 3 个线程在运行),该线程会被阻塞。 -
semaphore.release();
当前线程完成任务后,释放一个资源,让其他等待中的线程可以继续执行。
六、拓展建议
如果你希望进一步深入,可以尝试以下拓展:
- 将
acquire()
替换为tryAcquire()
,实现非阻塞式资源申请逻辑 - 与
QThreadPool
和QRunnable
结合使用,构建线程池限流机制 - 配合 GUI,加入任务进度条,构建一个多任务调度界面
- 使用更复杂的资源数量控制(例如一次申请多个资源)
七、总结
QSemaphore
是多线程控制中非常实用的一种同步机制,它能有效地控制线程对资源的并发访问数量。相比于 QMutex
的一对一互斥,QSemaphore
提供了更灵活的“多对多”资源控制能力。
在并发任务调度、限流、连接池管理等场景中,都是非常实用的解决方案。