实现思路
- 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
。 - 编译并运行程序,观察不同线程同步机制的效果。