使用 moveToThread 时是否需要锁定

Is locking necessary when using moveToThread

本文关键字:锁定 是否 moveToThread 使用      更新时间:2023-10-16

我搜索了这个网站和QT文档,但找不到并直接回答以下问题:

假设我有一个只有一个插槽的工人类:

void Worker::testSlot(){
  //access data and do some calculation
}

现在,如果此插槽连接到来自其他线程上运行的其他类的信号,并且如果使用排队连接,则在访问worker中的数据之前是否有必要使用锁定(QMutexLocker)?我认为不需要它,因为 testSlot() 总是在一个线程(工人在其中移动的线程)中执行,因此它是同步的。即使两个信号同时从不同的线程发出,也没有办法暂停第一个信号的中途执行插槽,而第二个信号则开始执行。但我不确定这一点。

你是 100% 正确的。

信息的关键位是,通过排队或自动连接发射连接到不同线程中的对象的信号会导致向目标对象发布QMetaCallEvent。它根本不直接导致任何调用。

在目标对象所在的线程中运行的事件循环将事件传递给对象 - 您可以通过正确重写 event 方法并在事件具有 MetaCall 类型时输出调试消息来验证这一点。请记住在重新实现中调用基类的方法。由于事件循环同步运行,因此它会串行执行调用。因此,不需要额外的序列化访问手段。元调用事件是从哪个线程发布的并不重要 - 线程本身不用于发布,无论从一个线程还是多个线程发布多个事件,事件队列看起来都是一样的。

它是处理QMetaCallEvent和执行调用的QObject::event方法。调用可以是槽、可调用方法、构造函数/析构函数或要在给定对象的线程上下文中执行的函子。