如何根据用户请求安全地停止正在运行的线程?

我正处于根据GUI上的用户操作在线程运行时必须终止线程的情况。 我在Windows上使用Qt 4.5.2。 一种方法是:

class MyThread : public QThread { QMutex mutex; bool stop; public: MyThread() : stop(false) {} void requestStop() { QMutexLocker(&mutex); stop = true; } void run() { while(counter1--) { QMutexLocker(&mutex); if (stop) return; while(counter2--) { } } } }; 

请注意,上述代码很少。 运行function在完成之前最多需要20秒,所以我想避免在循环中锁定和解锁mutex变量。 有没有比这种方法更快的方法。

提前致谢。

首先,看起来你不需要在你的整个内循环周围使用互斥锁,就像其他人所说的那样在if(停止)表达式周围,但我可能会错过你的一些应用程序上下文来明确地说出来。 也许你需要requestStop()来阻塞,直到线程退出。

如果减少的互斥范围对您来说足够,那么如果将停止变量声明为“volatile”,则根本不需要互斥锁。 “volatile”关键字导致(至少在VC ++下)读取/写入内存屏障被放置在停止访问周围,这意味着您的requestStop()调用保证会传递给您的线程而不是缓存。 以下代码在多核处理器上应该可以正常工作。

 class MyThread : public QThread { volatile bool stop; public: MyThread() : stop(false) {} void requestStop() { stop = true; } void run() { while(counter1--) { if (stop) return; while(counter2--) { } } } }; 

它不能直接满足您的需求,但您不能将您的互斥体范围更加严格吗?

 while(counter1--) { { QMutexLocker(&mutex); if (stop) return; } // End locking scope : we won't read it anymore until next time while(counter2--) ... 

您的代码中的主要问题是您持有的锁比实际需要的时间长得多。 检查stop变量后应解锁。 这应该会更快(取决于在内循环中完成的内容)。 无锁的替代方案是使用QAtomicInt

您可以使用临界区而不是互斥锁。 它们的开销略低。

否则你必须使用这种方法。 如果您希望工作线程在某个时间间隔t秒内终止,那么它需要每t秒至少检查一次终止事件。

为什么不使用可以定期检查的事件,让底层平台担心是否需要互斥锁来处理事件(我假设Qt有事件对象 – 我并不熟悉它)。 如果您使用事件对象,则平台会根据需要将处理该事件的任何关键部分范围缩短到一段时间。

此外,由于可能不会对该互斥锁进行太多争用(唯一的时间是某些东西想要杀死线程),抓取和释放互斥锁可能对性能影响很小。 在一个需要20秒运行的循环中,如果影响甚至可以测量,我会感到惊讶。 但也许我错了 – 尝试通过在使用和不使用互斥锁的情况下计算线程来测量它。 看看它是否真的需要关注你自己。

Qt似乎没有我正在谈论的那种事件对象(一个沿着Win32的事件对象),但是QSemaphore可以很容易地使用:

 class MyThread : public QThread { QSemaphore stopFlag; public: MyThread() : stopFlag( 1) {} void requestStop() { stopFlag.tryAcquire(); // decrement the flag (if it hasn't been already) } void run() { while(counter1--) { if (!stopFlag.available()) return; while(counter2--) { } } } };