我目前正在考虑QTimer
实现的线程安全性。
在我的应用程序中,我使用bool isActive()
方法来检查计时器是否正在运行。由于我计划使用这个方法也来自其他线程,我的想法转到线程安全考虑。
根据我的研究,bool isActive()
方法不是线程安全。
以下是我的假设:
QTimer
(QTimer源代码)的实现表明,bool isActive()
只是检查成员变量int id;
是否大于0:
inline bool isActive() const { return id >= 0; }
该成员变量在构造函数中使用INV_TIMER
初始化,该构造函数是对-1
的定义。当计时器启动时,它将被设置为int QObject::startTimer(int interval)
的返回值。
/*! \overload start()
Starts or restarts the timer with the timeout specified in \l interval.
If \l singleShot is true, the timer will be activated only once.
*/
void QTimer::start()
{
if (id != INV_TIMER) // stop running timer
stop();
nulltimer = (!inter && single);
id = QObject::startTimer(inter);
}
当对isActive()
的调用在QTimer::start()
期间从另一个线程执行时,我认为bool isActive()
的返回值可能无效。
我很感谢能够证实我的假设的人的意见。
为了达到线程安全,我只需用互斥结束对计时器的调用,如下面所示的代码片段所示。
class SensorControl : public QObject
{
Q_OBJECT
public:
SensorControl(); // inits and interval-settings are done at implementation
bool Start()
{
QMutexLocker lock(&m_mutexTimer);
return m_pTimer->start();
}
void Stop()
{
QMutexLocker lock(&m_mutexTimer);
return m_pTimer->stop();
}
bool IsMeasuring() const
{
QMutexLocker lock(&m_mutexTimer);
return m_pTimer->isActive();
}
private:
QMutex m_mutexTimer;
QTimer* m_pTimer;
};
发布于 2017-05-08 17:30:01
如果您只想从另一个线程调用QTimer::isActive
,那么您的解决方案看起来是安全的。isActive
只访问id
成员变量,因此您需要互斥-保护对id
的所有写入,以及从线程中读取id
。您是为isActive
和stop
这样做的,所以看起来很好。
请注意,如果您曾经调用QTimer
的其他写入id
的方法,您将得到未定义的行为。所以,注意不要调用像QTimer::setInterval()
、QTimer::~QTimer()
(!)这样的东西。诸若此类。此外,也不要使用单热计时器,因为这将写入id
中的QTimer::timerEvent()
。
通常,包装一个现有的类并添加互斥是危险的,这取决于所述类的内部结构,而且很难对所有情况进行检查。另外,在下一个Qt版本中,内部可能会发生变化,也许在下一个版本中,QTimer::timerEvent()
将无条件地更改id
,并且您的解决方案不再是线程安全了。
因此,虽然您的方法有效,但总的来说,我建议您不要这样做。
https://stackoverflow.com/questions/43853517
复制相似问题