QT:Qt多线程同步
来源:互联网 发布:sqlserver下载 64位 编辑:程序博客网 时间:2024/05/16 09:41
QT多线程同步
1 )互斥锁 :QMutex
保证同一时刻有指定多个线程访问共享资源。
void lock( );
void unlock( );
/** eg代码演示 **/
int g_count = 0; // 临界资源(全局变量) void ThreadA::run ( ) { g_count++; } void ThreadB::run ( ) { g_count++; } // g_count 大部分是2,有时为1BUG:'AB两个线程占用CPU资源的先后顺序有不确定的可能性',有bug可能【解决方法】 QMutex mutex; int g_count = 0; void ThreadA::run ( ) { mutex.lock ( ); // 锁定成功立即返回,失败则阻塞,等待另一个 g_count++; mutex.unlock ( ); } void ThreadB::run ( ) { mutex.lock ( ); // 加锁失败,原地等待-直到第一个线程调用了unlock ( ) g_count++; mutex.unlock ( ); } // g_count正确结果必定是2
2 ) 读写锁 :QReadWriteLock
QReadWriteLock lock;
int data;
void ReadThread::run (void) {
lock.lockForRread ( );
access_data_without_modity (&data); // 访问可以,不能修改 (逻辑)
lock.unlock ( );
}
void WriteThread::run (void) {
lock.lockForWrite ( );
modity_data (&data); // 写锁在逻辑上就只是为了修改
lock.unlock ( );
}
3 ) 信号量:QSemaphore UC - QT - 内核编程 - win32:信号量都一样
提供了一个通用的技术信号量,保证同一时刻有指定多个线程访问共享资源。
'PV操作' <==> 信号量是干什么用的?
P:申请资源,将信号量 - 1 ,S = S - 1 --->
减1以后如果S >= 0,该进程或线程继续执行,否则(S < 0)进入等待
'S:信号量,比如S为-2,说明有2个线程在等待/阻塞'
V:释放资源,将信号量 + 1 ,S = S + 1 --->
加1以后如果S > 0,什么都不做,代码则继续执行
加1以后如果S <= 0,说明有进程或线程正在等待/阻塞,加1时唤醒一个等待的进程或线程,唤醒哪一个线程在linux系统上是不确定的。
【总结】原语:原子性操作,保证线程执行是一定不会发生CPU资源切换。
// P: 获取信号量
void acquire(int n = 1);
// V: 释放信号量
void release(int n = 1);
《案例》生产者与消费者
定义两个信号量:
freeSpace: 控制生产者线程,如果仓库满,则阻塞等待;
usedSpace: 控制消费者线程,如果仓库空,则阻塞等待;
生产者:
while (1) {
P (freeSpace);
// 生产一个产品,放入仓库
V (usedSpace);
}
消费者:
while (1) {
P (usedSpace);
// 从仓库取出一个产品消费使用
V (freeSpace);
}
/** 代码演示 - 信号量实现**/
#include <QCoreApplication> // 它是QApplication的基类,没有图形界面的程序声明头文件#include <QThread>#include <QSemaphore>const int DataSize = 10; // 要生产的产品总量const int BufferSize = 5; // 存放产品的仓库大小int Buffer[BufferSize]; // 仓库// 控制生产者的信号量QSemaphore freeSpace (BufferSize);// 控制消费者的信号量QSemaphore usedSpace (0);// 生产者线程class threadProducer : public QThread {public: void run (void) { for (int i = 0; i < DataSize; i++) { // P 操作-1,获取信号量成功,仓库有空位,则生产1个 freeSpace.acquire (); Buffer[i % BufferSize] = i + 1; // Buffer[i % BufferSize],轮循(环形队列) qDebug ("Producer: %d", Buffer[i % BufferSize]); // V 操作+1,仓库中有可消费的产品,消费数量+1 usedSpace.release (); msleep (300); } }};// 消费者线程class threadConsumer : public QThread {public: void run (void) { for (int i = 0; i < DataSize; i++) { // P 操作-1,仓库有可消费的产品,则消费1个 usedSpace.acquire (); qDebug ("Consumer: %d", Buffer[i % BufferSize]); // V 操作+1,仓库中空闲位置多出1个,就可生产数量+1 freeSpace.release (); msleep (500); } }};int main (int argc, char** argv) { // QT核心应用程序,不包含ui QCoreApplication app (argc, argv); threadProducer producer; threadConsumer consumer; producer.start (); consumer.start (); producer.wait (); consumer.wait (); return app.exec ();}
4 ) 条件等待:QWaitCondition ---> 相当于UC中的条件变量
解决生产者消费者问题,使用条件等待(条件变量)更适用。
// 阻塞当前线程,解锁
bool wait(QMutex * lockedMutex);
// 唤醒所有阻塞的线程
void wakeAll( );
《案例》生产者与消费者 - 条件等待(变量)
【生产条件】缓冲区不满则生产,否则等待;
QWaitCondition bufferIsNotFull;
【消费条件】缓冲区不空则消费,否则等待;
QWaitCondition bufferIsNotEmpty;
/** 代码演示 - 条件等待(变量)实现 **/
#include <QCoreApplication>#include <QWaitCondition>#include <QMutex>#include <QThread>const int DataSize = 10; // 生产的产品总量const int BufferSize = 5; // 仓库的大小int buffer[BufferSize]; // 仓库// 生产条件:仓库不满则生产QWaitCondition bufferIsNotFull;// 消费条件:仓库不空则消费QWaitCondition bufferIsNotEmpty;// 互斥锁QMutex mutex;// 记录当前仓库的产品数量int usedSpace = 0;// 生产者线程类class threadProducer : public QThread {public: void run (void) { for (int i = 0; i < DataSize; i++) { mutex.lock (); while (usedSpace == BufferSize) { // 仓库满,则生产者阻塞等待 bufferIsNotFull.wait (&mutex); } // 仓库不满,开始生产++ buffer[i % BufferSize] = i + 1; qDebug ("Producer: %d", buffer[i % BufferSize]); ++usedSpace; // 记录产品个数 + 1 // 唤醒消费者线程,让消费这可以开始消费产品 bufferIsNotEmpty.wakeAll (); mutex.unlock (); msleep (300); } }};// 消费者线程类class threadConsumer : public QThread {public: void run (void) { for (int i = 0; i < DataSize; i++) { mutex.lock (); while (usedSpace == 0) { // 仓库为空,则消费者阻塞等待 bufferIsNotEmpty.wait (&mutex); } // 仓库不空,开始消费-- qDebug ("Consumer: %d", buffer[i % BufferSize]); --usedSpace; // 唤醒生产者线程,让生产者可以开始生产产品 bufferIsNotFull.wakeAll (); mutex.unlock (); msleep (700); } }};int main (int argc, char** argv) { QCoreApplication app (argc, argv); threadConsumer consumer; threadProducer producer; producer.start (); consumer.start (); producer.wait (); consumer.wait (); return app.exec ();}
<tips>
mkdir 目录
cd 目录
touch main.cpp
qmake -project
qtcreator & // 在QT中打开 open project,找到目录
- QT:Qt多线程同步
- Qt多线程同步总结
- QT多线程同步小结
- Qt多线程同步总结 .
- QT多线程同步小结
- Qt多线程同步总结
- QT多线程中的互斥与同步
- QT多线程中的互斥与同步
- QT多线程中的互斥与同步
- QT多线程同步 互斥缩 信号量 读写所 ...
- Qt: Qt多线程设计
- QT:Qt多线程创建
- Qt多线程基础(一)线程同步之互斥锁同步
- Qt多线程
- Qt多线程
- Qt多线程
- qt 多线程
- Qt多线程
- 最大K乘积
- mac mysql 重置root密码
- QT:Qt多线程创建
- 尺取法
- Lucene学习-CRUD
- QT:Qt多线程同步
- Linux时间参数atime、ctime、mtime
- windows搭建spark运行环境(windows scala,hadoop,spark安装,idea使用配置等)
- 部署 instance 到 OVS vlan100
- 1031. 查验身份证(15)-PAT乙级
- QT:Qt 网络编程基础
- 创建 OVS vlan101 并部署 instance
- 分析 OVS 如何实现 vlan 隔离
- QT:UDP网络编程实现