假设2个QThread
正在运行且具有以下关系:
connect(&Object1OfThread1, &Object1::Signal,
&Object2OfThread2, &Object2::Slot, Qt::QueuedConnection);
因此,当来自一个线程的对象发出信号时,将调用另一个线程的插槽。如Qt signals (QueuedConnection and DirectConnection)中所述,由于Qt::QueuedConnection
,Signal()
被发布/追加到Thread2的事件循环中。轮到时,将调用Slot()
。
问题:事件循环本身是线程安全的吗?
即如果Thread1和Thread3都同时向Thread2的事件循环发布了信号,该怎么办?
答案 0 :(得分:1)
this comment中提到的文章说,事件队列受互斥锁保护。
How Qt Signals and Slots Work - Part 3 - Queued and Inter Thread Connections
QueuedConnection
会将事件发布到事件循环中,以最终得到处理。发布事件时(在
QCoreApplication::postEvent
中),该事件将被推送到每个线程队列(QThreadData::postEventList
)中。 事件队列受互斥锁保护,因此当线程将事件推送到另一个线程的事件队列时,没有竞争条件。将事件添加到队列中之后,并且如果接收者居住在另一个线程中,我们将通过调用
QAbstractEventDispatcher::wakeUp
将该线程通知给事件调度程序。如果调度程序在等待更多事件时处于睡眠状态,这将唤醒调度程序。如果接收者在同一线程中,则事件将在事件循环迭代时稍后处理。
答案 1 :(得分:1)
Qt事件循环是线程安全的,但不是原子的。
线程安全
只要Object2OfThread2
的状态总是被与Thread2
关联的线程修改,就不会有任何竞争条件。任何时候最多只能执行一个插槽。
原子性
插槽的执行顺序受以下限制:
因此,我不建议为给定的插槽假定特定的执行顺序。
如果Thread1和Thread3都同时向Thread2的事件循环发布信号怎么办
Object2OfThread2
。Object2OfThread2, &Object2::Slot
之前进行的,则将在处理它们之前将其发布到Object2OfThread2
事件循环中。如果信号同时发出,则Thread3信号将首先排队,因此首先执行。