Qt的事件循环线程是安全的还是原子的?处理"队列连接"时如何同步?
Is Qt's event loop thread safe or atomic? How is it synchronised when dealing with `QueuedConnection`?
假设 2 个QThread
正在运行,具有以下关系:
connect(&Object1OfThread1, &Object1::Signal,
&Object2OfThread2, &Object2::Slot, Qt::QueuedConnection);
因此,当来自一个线程的对象引发信号时,将调用另一个线程的插槽。正如Qt信号(QueuedConnection和DirectConnection)中所讨论的,由于Qt::QueuedConnection
,Signal()
被发布/附加到Thread2的事件循环中。当它轮到时,Slot()
被调用。
问:事件循环本身是否线程安全?
即,如果线程 1 和线程 3 同时将信号发布到 Thread2 的事件循环中,该怎么办?
此评论中提到的文章说事件队列受互斥锁保护。
Qt信号和插槽的工作原理 - 第3部分 - 排队和线程间连接
QueuedConnection
会将事件发布到事件循环以最终处理。发布事件(
QCoreApplication::postEvent
年)时,事件将在每线程队列(QThreadData::postEventList
)中推送。事件队列受互斥锁保护,因此当线程将事件推送到另一个线程的事件队列时,没有争用条件。将事件添加到队列后,如果接收方位于另一个线程中,我们通过调用
QAbstractEventDispatcher::wakeUp
来通知该线程的事件调度程序。如果调度程序在等待更多事件时处于睡眠状态,这将唤醒调度程序。如果接收器位于同一线程中,则事件将在稍后处理,因为事件循环会迭代。
Qt事件循环是线程安全的,但不是原子的。
螺纹安全
只要Object2OfThread2
状态总是被与Thread2
关联的线程修改,就不会有任何竞争条件。最多一个插槽将在任何时候执行。
原子数
插槽的执行顺序由以下因素决定:
- 通常的线程抢占
- 与此插槽建立连接的顺序。
- 连接到信号的其他插槽。
所以我不建议假设给定插槽的特定执行顺序。
如果线程 1 和线程 3 同时将信号发布到 Thread2 的事件循环中,该怎么办
- 首先,它是不同的信号:两个线程不能发出同一对象的相同信号,因为该对象仅驻留在一个QObject中
- 首先连接的信号获胜,假设这些信号仅连接到
Object2OfThread2
,即使它们同时"发布"。 - 例如,如果 Thread1 信号连接到其他信号\插槽,并且这些连接是在
Object2OfThread2, &Object2::Slot
之前建立的,它们将在发布到事件循环Object2OfThread2
之前进行处理。如果信号同时发出,Thread3 信号将第一个排队,因此第一个执行。
- 当套接字连接断开时检测C/C++Unix
- 函数何时会在c++中包含stack_Unwind_Resume调用
- Python中的for循环与C++有何不同
- 松弛原子与无同步情况下的记忆连贯性
- 使用QQuickFramebufferObject时同步数据的最佳方式是什么
- 无法在windows上使用mingw将sqlite3与c连接
- 到连接组件算法的问题(递归)
- QTcpSocket在不阻塞GUI的情况下重新连接到服务器
- 无法在C++中建立与MySQL数据库的连接
- PC中的程序和PHONE中的本机描述应用程序之间的数据连接
- 在Qt Creator中,如何在连接到正在运行的进程后查看控制台输出
- 连接 dockerized 模型和 dockerized 数据库时出现"无法 SQLConnect"错误
- 使用 bfs 解决连接组件问题时得到错误的答案
- 在C++中同步线程
- 在C++的两个字符串中连接以逗号分隔的唯一值
- 当对套接字 send() 的同步调用由于连接另一端丢失而被阻止时,如何恢复?
- Qt的事件循环线程是安全的还是原子的?处理"队列连接"时如何同步?
- 英特尔®事务同步扩展新指令 (TSX-NI) 与英特尔 TSX 有何不同?
- 在BTooth模块连接时上传Arduino程序 avrdude: stk500_getsync(): 不同步: resp
- 无法检测到C++同步提升::asio::ip::tcp::套接字连接正在关闭