这种线程间通信方法安全吗?

时间:2011-09-28 17:20:40

标签: c++ multithreading qt signals-slots qwt

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

每个线程都连接到gui,并且在不同线程之间使用数据发送消息。每个线程基本上都处理它自己的列表。例如:

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

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

对象3:为obj 1生成数据并使用来自obj 2的数据。它有自己的内部数据结构,用于跟踪发送到obj 1的数据和来自obj 2的数据。它最终会推送两个数据集对某些QwtPlots进行一些分析之后。

Obj的1和2是实时的批评,并使用QueryPerformanceCounter风格的'timing',它们在运行时每次都会吸收CPU。他们每个循环运行QCoreApplication::processEvents()来处理通过的事件。

这是处理跨线程数据共享的好方法吗?如果不是,那么这些洞是什么?你会如何纠正它们?据我所知,这会产生很多“副本”的数据,但此时内存膨胀并不是一个问题。

提前感谢:)

1 个答案:

答案 0 :(得分:2)

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

  

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

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

  

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

您没有提到如何实现“pinging”或者哪些线程调用这些插槽。如果其他线程直接调用它们,并且如果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
}