我想使用Qt4实现多线程环境。这个想法如下c ++ - 类似伪代码:
class Thread : public QThread {
QList<SubThread*> threads_;
public:
void run() {
foreach(SubThread* thread : threads) {
thread.start();
}
foreach(SubThread* thread : threads) {
thread.wait();
}
}
void abort() {
foreach(SubThread* thread : threads) {
thread.cancel();
}
}
public slots:
// This method is called from the main-thread
// (sometimes via some signal-slot-connection)
void changeSomeSettings() {
abort();
// change settings
start();
}
}
class SubThread : public QThread {
bool isCancelled_;
public:
void run() {
while(!isCancelled or task completed) {
// something that takes some time...
}
}
void cancel() {
if(isRunning() {
isCancelled_ = true;
}
}
}
目的是使用slot changeSomeSettings()杀死所有正在运行的线程,提交其更改并重新启动它。我想要实现的是,一旦启动此方法,它将调用“abort”,然后等待所有线程终止。以错误的方式使用互斥:
void Thread::changeSomeSettings() {
mutex1.lock();
abort();
mutex2.lock();
start();
mutex1.unlock();
}
void Thread::run() {
foreach(Thread* thread : threads) {
thread.start();
}
foreach(Thread* thread : threads) {
thread.wait();
}
mutex2.unlock();
}
这实际上适用于Mac OSX下的Qt,但根据文档,mutex2必须在同一个线程中解锁(在Windows中我得到一个错误)。在不遇到赛车条件和死锁的情况下实现目标的最佳方法是什么?有没有比我在这里提出的更好的设计?
答案 0 :(得分:2)
您可能希望在这种情况下使用条件变量而不是互斥锁。条件变量是一个线程向另一个线程发出信号的方式。 QT的实施似乎是QTWaitCondition:
我可能让子线程定期检查条件变量的状态。这可以通过QTWaitCondition :: wait()以及短/ 0超时来完成。如果正在发出信号,则锁定包含更新数据的共享内存区域并访问需要更新的数据。然后该线程可以相应地安全地重启。
只是中止线程通常不是一个好主意。您可能最终泄漏内存/资源/句柄/锁/等。你不知道那个线程在它的调用堆栈中的位置,并且可能无法保证堆栈将为你“解开”并且所有析构函数都被调用。这是子线程定期检查条件变量以获取更新数据并让它们使用新数据安全地重新启动的另一个原因。