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();
}
相关推荐
小短腿的代码世界15 小时前
Qt实时盈亏计算深度解析:从持仓数据到动态盈亏展示
开发语言·qt
Python私教16 小时前
GenericAgent PySide6 桌面应用深度解析:悬浮按钮 + 聊天面板的原生 Qt 方案
开发语言·数据库·qt
用户8055336980316 小时前
现代Qt开发教程(新手篇)1.11——定时器
c++·qt
小短腿的代码世界18 小时前
Qt券商接口封装深度解析:统一API设计与多源适配
开发语言·qt·单元测试
T0uken18 小时前
基于 vcpkg 与 LLVM-MinGW 的 Qt6 静态链接开发方案
c++·windows·qt
Ulyanov19 小时前
《现代 Python 桌面应用架构实战:PySide6 + QML 从入门到工程化》 开发环境搭建与工具链极简主义 —— 拒绝臃肿,构建工业级基座
开发语言·python·qt·ui·架构·系统仿真
(Charon)1 天前
【C++/Qt】Qt 实现 MQTT 测试工具:连接 Broker、订阅主题与发布消息
开发语言·c++·qt
Ulyanov1 天前
《现代 Python 桌面应用架构实战:PySide6 + QML 从入门到工程化》:动态数据仪表盘与 NumPy 可视化 —— 从标量到向量的数据驱动进化
开发语言·python·qt·架构·numpy
小短腿的代码世界1 天前
Qt序列化与持久化深度解析:从QDataStream到自定义二进制协议
开发语言·数据库·qt
誰能久伴不乏1 天前
Qt/C++ 架构之美:用一个“水龙头”隐喻,讲透面向接口编程与彻底解耦
c++·qt·架构