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

我有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()来处理通过的事件.

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

提前致谢 :)

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

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
}
点赞