Qt Lock&Semaphore

QMutex

QMutex 是 Qt 框架提供的互斥锁类,用于保护共享资源的访问,实现线程间的互斥操作。在多线程环境下,通过互斥锁来控制对共享数据的访问,确保线程安全。

c++ 复制代码
QMutex mutex;

mutex.lock(); // 加锁
// ... 共享资源
mutex.unlock(); // 解锁

QMutexLocker

QMutexLocker 是 QMutex 的辅助类,简化对互斥锁的上锁和解锁操作,避免忘记解锁导致的死锁等问题。

c++ 复制代码
QMutex mutex;
{
    QMutexLocker locker(mutex); // 在作用域内自动上锁,出了作用域自动解锁
}

QReadWriteLocker、QReadLocker、QWriteLocker

  • QReadWriteLock :读写锁类,用于控制读和写的并发访问。

  • QReadLocker :用于读操作上锁,允许多个线程同时读取共享资源。

  • QWriteLocker :用于写操作上锁,只允许一个线程写入共享资源。

多个线程可以同时读取共享数据,但只有一个线程能够进行写操作。读写锁提供了更高效的并发访问方式。

c++ 复制代码
QReadWriteLock rwLock;

// 在读操作中使用读锁
{
    QReadLocker locker(&rwLock); // 在作用域内自动上读锁,出了作用域自动解锁
    // 读取共享资源
    // ...
}

// 在写操作中使用写锁
{
    QWriteLocker locker(&rwLock); // 在作用域内自动上写锁,出了作用域自动解锁
    // 修改共享资源
    // ...
} 

信号量

QSemaphore

QSemaphore 是 Qt 框架提供的计数信号量类,用于控制同时访问共享资源的线程数量。

c++ 复制代码
QSemaphore semaphore(2); // 同时允许两个线程访问共享资源

// 在需要访问共享资源的线程中
semaphore.acquire(); // 尝试获取信号量,若已满则阻塞
// 访问共享资源
// ...
semaphore.release(); // 释放信号量

// 在另一个线程中进行类似操作

QWaitCondition

QWaitCondition 是Qt中的一个类,用于在多线程编程中实现线程同步。它允许一个线程通知其他线程某个条件已经满足,从而协调线程之间的工作。QWaitCondition通常与QMutex一起使用,以确保线程安全。

在生产者-消费者模型中,生产者线程负责生成数据,而消费者线程负责处理数据。QWaitCondition可以用来协调生产者和消费者之间的工作,确保数据的正确读写。

  • wait:用于让线程在条件未满足时阻塞等待,直到被其他线程通过 wakeOne()wakeAll() 唤醒,或者等待超时;在使用时必须传入一个上锁的 QMutex 对象
  • wakeAll:在满足特定条件时唤醒所有等待线程
  • wakeOne:在满足特定条件时随机唤醒一个正在等待的线程
c++ 复制代码
onst int data_size = 50;
const int buf_size = 10;
char buffer[buf_size];

QWaitCondition buffer_is_not_full;
QWaitCondition buffer_is_not_empty;
QMutex mutex;
int used_space=0;

class Producer : public QThread {
protected:
    void run() {
        for (int i = 0; i < data_size; ++i) {
            mutex.lock();
            while (used_space == buf_size) {     // 如果buffer已经满了,这时不能再生产了
                buffer_is_not_full.wait(&mutex); // 等待buffer_is_not_full调用wakeAll/wakeOne,否则继续阻塞
                							  // 等待mutex 释放
            }
            std::cerr<<"a";
            ++used_space;
            buffer_is_not_empty.wakeAll();        // 唤醒消费线程
            mutex.unlock();
        }
    }
};

class Consumer : public QThread {
protected:
    void run() {
        for (int i = 0; i < data_size; ++i) {
            mutex.lock();
            while (used_space == 0) { // buffer已经空了,这时不能再消费类了
                buffer_is_not_empty.wait(&mutex); // 等待buffer_is_not_empty调用wakeAll/wakeOne,否则继续阻塞
            }
            std::cerr<<"b";
            --used_space;
            buffer_is_not_full.wakeAll(); // 唤醒生产线程
            mutex.unlock();
        }
        std::cerr<<std::endl;
    }
};

int main(int argc, char *argv[]) {
    QCoreApplication app(argc, argv);
    Producer producer;
    Consumer consumer;
    producer.start();
    consumer.start();
    producer.wait();
    consumer.wait();
	return app.exec();
}
相关推荐
luoyayun3611 小时前
Qt + FFmpeg 音频工具:重采样实现
qt·ffmpeg·重采样
小短腿的代码世界20 小时前
Qt Bluetooth源码深度解析:从HCI协议到跨平台API的完整架构
开发语言·qt·架构
小短腿的代码世界21 小时前
Qt WebEngine多进程架构与IPC通信:从Chromium多进程到Qt信号槽融合
qt·架构·系统架构
尘中远1 天前
【Qwt 7.0 系列】快速入门与核心新特性概览 —— 更现代的 Qt 数据可视化库
qt·数据可视化·绘图·qwt·科学绘图
初阳7851 天前
【Qt】系统相关(3)——多线程
qt
初阳7851 天前
【Qt】系统相关(2)——文件
开发语言·qt
尘中远2 天前
【Qwt 7.0 系列】坐标轴与刻度系统 —— 刻度引擎、网格、图例与刻度朝内
qt·数据可视化·qcustomplot·qwt·工业软件·科学绘图
sycmancia2 天前
Qt——多线程间的互斥
开发语言·qt
尘中远2 天前
【Qwt 7.0 系列】常用图表类型实战 —— 柱状图、散点图、箱线图与直方图
qt·qwt·工业软件·科学绘图
尘中远2 天前
【Qwt 7.0 系列】交互功能详解 —— 平移、缩放、坐标轴交互与数据拾取
qt·数据可视化·绘图·qcustomplot·qwt·科学绘图