还在为多线程数据竞争和死锁问题头疼?本文通过4个真实代码示例,深度剖析:
示例代码:
class Data : public std::enable_shared_from_this<Data> {
public:
Data() { startWorkerThread(); }
~Data() { stopWorkerThread(); }
private:
class Worker;
std::unique_ptr<Worker> m_worker;
std::atomic<int> data{0};
void startWorkerThread() {
if(m_worker)
return;
m_worker = std::make_unique<Worker>(shared_from_this());
// 启动线程
m_worker->start();
}
void stopWorkerThread() {
if (m_worker) {
m_worker->stop();
m_worker.reset();
}
}
};
class Data::Worker {
public:
Worker(std::shared_ptr<Data> data){
m_data = data;
}
~Woker(){}
void start(){
m_stop = false;
if(m_thread.joinable()) {
m_thread.join();
}
m_thread = std::thread([this] { run(); });
}
void stop(){
m_stop = true;
if(m_thread.joinable()) {
m_thread.join();
}
}
private:
std::atomic<bool> m_stop{false};
std::thread m_thread;
std::weak_ptr <Data> m_data; // 使用弱指针,避免循环引用
void run() {
while(!m_stop){
auto data_ptr = m_data.lock();
if(!data_ptr) {
std::this_thread::sleep_for(std::chrono::milliseconds(50));
continue;
}
int data = m_data->data.load(std::memory_order_acquire);
if (data > 0) {
auto temp = data * 3 / 2;
m_data->data.store(temp, std::memory_order_release);
}
std::this_thread::sleep_for(std::chrono::milliseconds(2));
}
}
};
// 用户必须通过 shared_ptr 创建 Data 对象
auto data = std::make_shared<Data>();
示例代码:
#include
#include
class Data {
public:
void decrement() {
std::lock_guard<std::mutex> lock(m_mutex);
if (data > 0) data--;
}
int get() const {
std::lock_guard<std::mutex> lock(m_mutex);
return data;
}
private:
mutable std::mutex m_mutex;
int data = 0;
};
class Worker {
public:
explicit Worker(std::shared_ptr<Data> data) : m_data(data), m_stop(false) {}
void start() {
m_thread = std::thread([this] {
while (!m_stop.load(std::memory_order_acquire)) {
m_data.decrement();
std::this_thread::sleep_for(std::chrono::milliseconds(2));
}
});
}
void stop() {
m_stop.store(true, std::memory_order_release);
if (m_thread.joinable()) m_thread.join();
}
private:
std::weak_ptr<Data> m_data; // 使用弱指针,避免循环引用
std::atomic<bool> m_stop;
std::thread m_thread;
};
int main(){
std::shared_ptr<Data> data = std::make_shared<Data>();
Worker worker(data);
worker.start();
std::this_thread::sleep_for(std::chrono::seconds(5));
worker.stop();
return 0;
}
示例代码:
#include
class Data {
public:
Data() : m_total(0), m_count(0) {}
void calculate(int value) {
m_total.fetchAndAddOrdered(value); // 原子加法
m_count.fetchAndAddOrdered(1); // 原子递增
}
int getAverage() const {
const int count = m_count.loadAcquire();
const int total = m_total.loadAcquire();
return (count == 0) ? 0 : total / count;
}
private:
QAtomicInt m_total; // 总和
QAtomicInt m_count; // 计数
};
class Worker : public QThread {
Q_OBJECT
public:
// 通过智能指针管理Data所有权
explicit Worker(QPointer data, QObject* parent = nullptr)
: QThread(parent), m_data(data), m_stop(false) {}
void stop() {
m_stop = true;
if (isRunning()) {
quit();
wait(); // 等待线程结束
}
}
signals:
void averageUpdated(int value);
protected:
void run() override {
QRandomGenerator rand(QTime::currentTime().msec());
while (!m_stop) {
// 检查Data指针有效性
if (m_data.isNull()) break;
// 更新数据并通知
const int num = rand.bounded(1, 100);
m_data->calculate(num);
emit averageUpdated(m_data->getAverage());
QThread::msleep(100);
}
}
private:
QPointer m_data; // 共享数据指针
QAtomicInteger m_stop{false};
};
int main(){
QPointer data = new Data();
// 启动工作线程
Worker worker(data);
QObject::connect(&worker, &Worker::averageUpdated, [](int avg) { qDebug() << "Current average:" << avg; });
worker.start();
// 运行5秒后停止
QTimer::singleShot(5000, [&worker] {
worker.stop();
});
return 0;
}
示例代码:
class Data {
public:
void calculate(int value) {
QMutexLocker locker(&m_mutex);
m_total += value;
m_count++;
}
int getAverage() const {
QMutexLocker locker(&m_mutex);
return (m_count == 0) ? 0 : m_total / m_count;
}
private:
mutable QMutex m_mutex; // 允许const方法加锁
int m_total = 0;
int m_count = 0;
};
class Worker : public QObject {
Q_OBJECT
public:
explicit Worker(QPointer<Data> data, QObject* parent = nullptr) : QObject(parent), m_data(data) {}
void start() {
QRandomGenerator rand;
while (!m_stop) {
// 检查指针有效性
if (!m_data) break;
// 更新数据并通知
const int num = rand.bounded(1, 100);
m_data->calculate(num);
emit averageUpdated(m_data->getAverage());
QThread::msleep(100);
}
emit workFinished();
}
void stop() {
m_stop = true;
}
signals:
void averageUpdated(int value);
void workFinished();
private:
QPointer<Data> m_data;
std::atomic<bool> m_stop{false};
};
int main(){
QThread thread = new QThread();
QPointer<Data> data = QPointer<Data>(new Data());
Worker worker(data);
worker.moveToThread(thread);
QObject::connect(thread, &QThread::finished, [thread] {
thread->quit();
thread->deleteLater();
});
QObject::connect(thread, &QThread::started, [worker] {
worker.start();
});
QObject::connect(&worker, &Worker::averageUpdated, [](int avg) { qDebug() << "Current average:" << avg; });
QObject::connect(&worker, &Worker::workFinished, [thread] { thread->quit(); });
// 启动线程
thread->start();
// 运行5秒后停止
QTimer::singleShot(5000, [&worker] {
worker.stop();
worker.quit();
worker.wait();
});
return 0;
};
优点:
缺点:
适用场景:
优点:
缺点:
适用场景:
优点:
缺点:
适用场景:
优点:
缺点:
适用场景:
特征需求 | 推荐方案 |
---|---|
超高频计数器更新 | 原子控制 |
复杂数据结构保护 | 互斥锁 |
Qt GUI程序后台计算 | QThread |
事件驱动的异步任务 | moveToThread |
跨平台通用逻辑 | 原子控制/互斥锁 |
需要精细控制内存顺序 | 原子控制(memory_order) |
需要与界面元素频繁交互 | QThread/moveToThread |