c++ - 这种线程间通信的方法安全吗?

标签 c++ multithreading qt signals-slots qwt

我有 3 个对象(继承自 QObject),每个对象都包含一个单独的 std::list。每个对象都在主 gui 线程(没有父线程)中创建,然后被推送到它自己的线程(使用 Qt 的 QObject::moveToThread())。

每个线程都连接到一个图形用户界面,消息在不同线程之间发送数据。每个线程本质上是处理它自己的列表。例如:

目标 1:数据消费者。它弹出列表的前面(如果存在数据)以供使用。它还有一个可用的 SLOT,以便其他线程可以向它推送数据。没有其他对象可以直接访问此列表,只有原始 QObject 类。

目标 2:数据的生产者。它将数据推送到它的列表中。它有 SLOTS 可供其他人“ping”它以获取数据,而这些数据又会从其列表中发出 SIGNAL 弹出数据。没有其他对象可以直接访问此列表。

Obj 3:为 obj 1 生产数据并使用 obj 2 的数据。它有自己的内部数据结构,用于跟踪发送到 obj 1 的数据和来自 obj 2 的数据。它最终将推送两个数据集在它做了一些分析之后到一些QwtPlots

Obj 的 1 和 2 是实时关键的,并使用 QueryPerformanceCounter 风格的“计时”,这实际上会在它们运行时消耗 CPU 资源。他们在每个循环中运行 QCoreApplication::processEvents() 来处理通过的事件。

这是处理跨线程数据共享的好方法吗?如果不是,漏洞在哪里,您将如何纠正它们?我知道这会创建大量的数据“拷贝”,但此时内存膨胀不是问题。

提前致谢:)

最佳答案

如果没有所有的实现细节,很难确切地说它是否是线程安全的,因为在使用线程时有很多事情可能出错。

Obj 1 : Consumer of data. It pop's the front off of its list(if data is present) to use. It also has a SLOT available so that other threads can push data to it. No other object can access this list directly only the the original QObject class.

如果此插槽使用排队或自动连接类型连接到其他线程(例如 Obj 3)中的信号,则 Obj 1 可能是安全的。如果插槽直接从其他线程调用,那么它显然不是线程安全的,除非您显式同步所有内容。

Obj 2 : Producer of data. It pushes data to its list. It has SLOTS available for others to 'ping' it for data which will in turn emit a SIGNAL popping data from its list. No other object can access this list directly.

您没有提到“ping”是如何实现的,也没有提到哪些线程调用了这些插槽。如果其他线程直接调用它们并且 ping 涉及访问内部 std::list,那么您就有麻烦了。如果这些插槽仅通过排队或自动连接调用(例如,到 Obj 3 中的某个信号),则没问题。如果这些插槽是线程安全的(例如,它们只将“ping”消息放入某种内部同步消息队列),那么也可以。不过,后一种方式看起来像是排队连接机制的自定义重新实现。

总的来说,这整件事对我来说太危险了,因为可以从任何地方错误地调用插槽。我会通过在此处进行一些安全检查来尝试避免这种情况,如下所示:

void Obj2::ping() {
    if (QThread::currentThread() != this->thread()) {
        // not sure how efficient it is
        QMetaObject::invoke(this, "ping", Qt::QueuedConnection);
        return;
    }
    // thread unsafe code goes here
}

关于c++ - 这种线程间通信的方法安全吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7587071/

相关文章:

c++ - 将文件中的utf-8字符转换为十六进制

c++ - 用于模式识别/图像处理的 C 或 C++?

c++ - 如何缩短 Visual Studio 中的链接过程

c# - 多线程 WebRequest 调用和争用

ios - Unwind Segue 和多线程

c++ - Qt 4.8 : connection behavior between two signals and one slot from different threads

c++ - C++/Qt 中变量的别名?

c++ - 如何以这种方式对齐 qtreewidget 列中的文本 : "...qtreewidgetitemdata" instead of "qtreewidgetitemdata..."?

c++ - Bazel- 问题导入头文件

c++ - Qt NetworkAccessManager 完成信号