我有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()
来处理通过的事件。
这是处理跨线程数据共享的好方法吗?如果不是,那么这些洞是什么?你会如何纠正它们?据我所知,这会产生很多“副本”的数据,但此时内存膨胀并不是一个问题。
提前感谢:)
答案 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
}