1

假设 2 QThreads 以下列关系运行:

connect(&Object1OfThread1, &Object1::Signal, 
        &Object2OfThread2, &Object2::Slot, Qt::QueuedConnection);

因此,当来自一个线程的对象发出信号时,会调用另一个线程的插槽。正如Qt 信号(QueuedConnection 和 DirectConnection)中所讨论的,由于Qt::QueuedConnectionSignal()被发布/附加到 Thread2 的事件循环中。当它轮到时,Slot()被调用。

问题:事件循环本身是线程安全的吗?
即。如果 Thread1 和 Thread3 都同时向 Thread2 的事件循环发布信号怎么办。

4

2 回答 2

2

Qt 事件循环是线程安全的,但不是原子的。

线程安全

只要Object2OfThread2状态总是由与 关联的线程修改Thread2,就不会有任何竞争条件。任何时候最多执行一个槽。

原子性

插槽的执行顺序受以下约束:

  • 普通线程抢占
  • 与此插槽建立连接的顺序。
  • 其他插槽连接到信号。

所以我不建议为给定的插槽假设特定的执行顺序。

如果 Thread1 和 Thread3 都同时向 Thread2 的事件循环发布信号怎么办

  • 首先,它是不同的信号:两个线程不能为同一个对象发出相同的信号,因为这个对象只存在于一个 QObject 中
  • 首先连接的信号获胜,假设这些信号仅连接到,Object2OfThread2即使它们同时“发布”。
  • 例如,如果 Thread1 信号连接到其他信号\插槽,并且这些连接是在之前建立的Object2OfThread2, &Object2::Slot,则它们将在发布到Object2OfThread2事件循环之前进行处理。如果信号同时发出,Thread3 信号将最先排队,因此最先执行。
于 2019-04-12T10:44:47.097 回答
2

此评论中提到的文章说,事件队列受互斥体保护。

Qt 信号和插槽如何工作 - 第 3 部分 - 队列和线程间连接

AQueuedConnection会将事件发布到事件循环以最终被处理。

发布事件时(in QCoreApplication::postEvent),该事件将被推送到每个线程队列(QThreadData::postEventList)中。事件队列受互斥体保护,因此当线程将事件推送到另一个线程的事件队列时,没有竞争条件

一旦事件被添加到队列中,并且如果接收者在另一个线程中,我们通过调用通知该线程的事件调度器QAbstractEventDispatcher::wakeUp。如果调度程序在等待更多事件时处于睡眠状态,这将唤醒调度程序。如果接收者在同一个线程中,则事件将在稍后处理,因为事件循环会迭代。

于 2019-04-11T02:28:27.280 回答