实现思路
QThread 类简介 :
QThread
是 Qt 中用于多线程编程的基础类。可以通过继承 QThread
并重写 run()
方法来创建自定义的线程逻辑。新线程的执行从 run()
开始,调用 start()
方法启动线程。 掷骰子的多线程应用程序 :
创建一个 DiceThread
类继承自 QThread
,在 run()
方法中模拟掷骰子操作,并通过信号将结果发送出去。 线程同步 :
线程同步的概念 :确保多个线程之间协调操作,避免数据竞争和不一致性。基于互斥量的线程同步 :使用 QMutex
确保在同一时间只有一个线程可以访问共享资源。基于读写锁的线程同步 :使用 QReadWriteLock
,允许多个读线程同时访问资源,但写线程独占资源。基于条件等待的线程同步 :使用 QWaitCondition
与 QMutex
结合,允许线程等待某个条件满足。基于信号量的线程同步 :使用 QSemaphore
控制对资源的访问数量。
代码示例
1. QThread 类简介和掷骰子的多线程应用程序
# include <QtWidgets/QApplication>
# include <QtCore/QThread>
# include <QtCore/QRandomGenerator>
# include <QtCore/QDebug>
# include <QtCore/QMutex>
# include <QtCore/QReadWriteLock>
# include <QtCore/QWaitCondition>
# include <QtCore/QSemaphore>
class DiceThread : public QThread {
Q_OBJECT
signals:
void resultReady ( int result) ;
protected :
void run ( ) override {
while ( ! isInterruptionRequested ( ) ) {
int diceValue = QRandomGenerator :: global ( ) -> bounded ( 1 , 7 ) ;
emit resultReady ( diceValue) ;
msleep ( 1000 ) ;
}
}
} ;
int main ( int argc, char * argv[ ] ) {
QApplication app ( argc, argv) ;
DiceThread diceThread;
QObject :: connect ( & diceThread, & DiceThread:: resultReady, [ ] ( int result) {
qDebug ( ) << "Dice result: " << result;
} ) ;
diceThread. start ( ) ;
QThread :: sleep ( 10 ) ;
diceThread. requestInterruption ( ) ;
diceThread. wait ( ) ;
return app. exec ( ) ;
}
# include "main.moc"
2. 基于互斥量的线程同步
# include <QtWidgets/QApplication>
# include <QtCore/QThread>
# include <QtCore/QRandomGenerator>
# include <QtCore/QDebug>
# include <QtCore/QMutex>
class SharedData {
public :
int value = 0 ;
QMutex mutex;
} ;
class IncrementThread : public QThread {
public :
IncrementThread ( SharedData * data) : data ( data) { }
protected :
void run ( ) override {
for ( int i = 0 ; i < 1000 ; ++ i) {
data-> mutex. lock ( ) ;
++ data-> value;
data-> mutex. unlock ( ) ;
msleep ( 1 ) ;
}
}
private :
SharedData * data;
} ;
int main ( int argc, char * argv[ ] ) {
QApplication app ( argc, argv) ;
SharedData sharedData;
IncrementThread thread1 ( & sharedData) ;
IncrementThread thread2 ( & sharedData) ;
thread1. start ( ) ;
thread2. start ( ) ;
thread1. wait ( ) ;
thread2. wait ( ) ;
qDebug ( ) << "Final value: " << sharedData. value;
return app. exec ( ) ;
}
# include "main.moc"
3. 基于读写锁的线程同步
# include <QtWidgets/QApplication>
# include <QtCore/QThread>
# include <QtCore/QRandomGenerator>
# include <QtCore/QDebug>
# include <QtCore/QReadWriteLock>
class SharedData {
public :
int value = 0 ;
QReadWriteLock lock;
} ;
class ReadThread : public QThread {
public :
ReadThread ( SharedData * data) : data ( data) { }
protected :
void run ( ) override {
for ( int i = 0 ; i < 1000 ; ++ i) {
data-> lock. lockForRead ( ) ;
qDebug ( ) << "Read value: " << data-> value;
data-> lock. unlock ( ) ;
msleep ( 1 ) ;
}
}
private :
SharedData * data;
} ;
class WriteThread : public QThread {
public :
WriteThread ( SharedData * data) : data ( data) { }
protected :
void run ( ) override {
for ( int i = 0 ; i < 100 ; ++ i) {
data-> lock. lockForWrite ( ) ;
++ data-> value;
data-> lock. unlock ( ) ;
msleep ( 10 ) ;
}
}
private :
SharedData * data;
} ;
int main ( int argc, char * argv[ ] ) {
QApplication app ( argc, argv) ;
SharedData sharedData;
ReadThread reader1 ( & sharedData) ;
ReadThread reader2 ( & sharedData) ;
WriteThread writer ( & sharedData) ;
reader1. start ( ) ;
reader2. start ( ) ;
writer. start ( ) ;
reader1. wait ( ) ;
reader2. wait ( ) ;
writer. wait ( ) ;
qDebug ( ) << "Final value: " << sharedData. value;
return app. exec ( ) ;
}
# include "main.moc"
4. 基于条件等待的线程同步
# include <QtWidgets/QApplication>
# include <QtCore/QThread>
# include <QtCore/QRandomGenerator>
# include <QtCore/QDebug>
# include <QtCore/QMutex>
# include <QtCore/QWaitCondition>
class SharedData {
public :
int value = 0 ;
QMutex mutex;
QWaitCondition condition;
bool ready = false ;
} ;
class ProducerThread : public QThread {
public :
ProducerThread ( SharedData * data) : data ( data) { }
protected :
void run ( ) override {
QRandomGenerator gen;
for ( int i = 0 ; i < 10 ; ++ i) {
QThread :: msleep ( 1000 ) ;
data-> mutex. lock ( ) ;
data-> value = gen. bounded ( 1 , 100 ) ;
data-> ready = true ;
data-> condition. wakeOne ( ) ;
data-> mutex. unlock ( ) ;
}
}
private :
SharedData * data;
} ;
class ConsumerThread : public QThread {
public :
ConsumerThread ( SharedData * data) : data ( data) { }
protected :
void run ( ) override {
while ( true ) {
data-> mutex. lock ( ) ;
if ( ! data-> ready) {
data-> condition. wait ( & data-> mutex) ;
}
qDebug ( ) << "Consumed value: " << data-> value;
data-> ready = false ;
data-> mutex. unlock ( ) ;
}
}
private :
SharedData * data;
} ;
int main ( int argc, char * argv[ ] ) {
QApplication app ( argc, argv) ;
SharedData sharedData;
ProducerThread producer ( & sharedData) ;
ConsumerThread consumer ( & sharedData) ;
consumer. start ( ) ;
producer. start ( ) ;
return app. exec ( ) ;
}
# include "main.moc"
5. 基于信号量的线程同步
# include <QtWidgets/QApplication>
# include <QtCore/QThread>
# include <QtCore/QRandomGenerator>
# include <QtCore/QDebug>
# include <QtCore/QSemaphore>
class SharedResource {
public :
QSemaphore semaphore;
void useResource ( ) {
semaphore. acquire ( ) ;
qDebug ( ) << "Using resource..." ;
QThread :: msleep ( 100 ) ;
semaphore. release ( ) ;
}
} ;
class UserThread : public QThread {
public :
UserThread ( SharedResource * resource) : resource ( resource) { }
protected :
void run ( ) override {
for ( int i = 0 ; i < 10 ; ++ i) {
resource-> useResource ( ) ;
}
}
private :
SharedResource * resource;
} ;
int main ( int argc, char * argv[ ] ) {
QApplication app ( argc, argv) ;
SharedResource resource;
resource. semaphore. release ( 3 ) ;
UserThread thread1 ( & resource) ;
UserThread thread2 ( & resource) ;
UserThread thread3 ( & resource) ;
thread1. start ( ) ;
thread2. start ( ) ;
thread3. start ( ) ;
thread1. wait ( ) ;
thread2. wait ( ) ;
thread3. wait ( ) ;
return app. exec ( ) ;
}
# include "main.moc"
代码解释
1. QThread 类简介和掷骰子的多线程应用程序
DiceThread 类 :
继承 QThread
并在 run()
中模拟掷骰子操作,使用 QRandomGenerator
生成 1 到 6 的随机数。 通过 resultReady
信号将结果发送出去,在主线程中连接该信号并打印结果。
2. 基于互斥量的线程同步
SharedData 类 :
IncrementThread 类 :
每次循环对 value
加 1 前先加锁,加 1 后解锁,确保同一时间只有一个线程修改 value
。
3. 基于读写锁的线程同步
SharedData 类 :
包含一个 value
变量和 QReadWriteLock
。 ReadThread 类 :
读线程使用 lockForRead()
锁定,读取 value
后解锁。 WriteThread 类 :
写线程使用 lockForWrite()
锁定,修改 value
后解锁,写线程独占资源,读线程可同时读。
4. 基于条件等待的线程同步
SharedData 类 :
包含 value
、QMutex
、QWaitCondition
和 ready
标志。 ProducerThread 类 :
生产者线程生成数据,使用 wakeOne()
唤醒等待的消费者。 ConsumerThread 类 :
消费者线程等待 ready
标志,使用 wait()
等待,一旦有数据可用,打印并重置 ready
。
5. 基于信号量的线程同步
SharedResource 类 :
包含 QSemaphore
,初始释放 3 个资源。 UserThread 类 :
每次使用资源前先 acquire()
资源,使用后 release()
资源,确保最多 3 个线程同时使用资源。
使用说明
对于每个示例,将代码保存为 main.cpp
文件。 确保 .pro
文件包含 QT += core widgets
以及 CONFIG += c++11
。 编译并运行程序,观察不同线程同步机制的效果。