这种线程间通信方法安全吗?
Is this method of inter-thread-communication safe?
我有3个对象(从QObject
继承),每个对象都包含一个单独的std::list
。每个对象被创建在主gui线程(没有父),然后被推到它自己的线程(使用Qt的QObject::moveToThread()
)。
每个线程都连接到一个gui,消息在不同的线程之间发送。每个线程基本上都要处理它自己的列表。例如:
Obj 1:数据的消费者。它是要使用的列表的前面(如果有数据)。它还有一个可用的SLOT,以便其他线程可以向它推送数据。没有其他对象可以直接访问这个列表,只有原始的QObject类。
Obj 2:数据的生产者。它将数据推入它的列表。它有可用的插槽供其他"ping"它的数据,这将反过来从它的列表中发出一个信号弹出数据。没有其他对象可以直接访问此列表。
Obj 3:为Obj 1生成数据,并从Obj 2消费数据。它有自己的内部数据结构来跟踪发送到obj 1和来自obj 2的数据。在做了一些分析之后,最后将两个数据集推到某个QwtPlots
。
Obj的1和2是实时关键的,并使用QueryPerformanceCounter风格的"计时",这将在它们运行时基本上占用一个CPU。它们每个循环运行QCoreApplication::processEvents()
来处理传入的事件。
这是处理跨线程数据共享的好方法吗?如果不是,漏洞在哪里,你会如何纠正它们?我知道这将创建大量的数据"副本",但是内存膨胀在这一点上不是一个问题。
提前感谢:)
如果没有所有的实现细节,很难确切地说它是否线程安全,因为在使用线程时有很多事情可能出错。
Obj 1:数据的消费者。它是要使用的列表的前面(如果有数据)。它还有一个可用的SLOT,以便其他线程可以向它推送数据。没有其他对象可以直接访问这个列表,只有原始的QObject类。
如果该槽使用排队或自动连接类型连接到其他线程(如Obj 3)中的信号,则Obj 1可能是安全的。如果槽是直接从其他线程调用的,那么它显然不是线程安全的,除非你显式地同步所有内容。
Obj 2:数据的生产者。它将数据推入它的列表。它有可用的插槽供其他"ping"它的数据,这将反过来从它的列表中发出一个信号弹出数据。没有其他对象可以直接访问此列表。
你没有提到"ping"是如何实现的,或者哪些线程调用这些插槽。如果其他线程直接调用它们,并且ping涉及访问内部std::列表,那么您就有麻烦了。如果这些插槽只能通过排队或自动连接调用(例如,对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
}
- 将传入的网络"char*"数据转换为"uint8_t"并返回的安全方法是什么?
- 在 c++ 中从执行的 shell 命令获取返回状态的安全方法是什么?
- 在C++线程内实现多个计时器的最安全方法
- 最有效的安全方法将 std::map<int, std::shared_ptr> 转换为 std::<Base>map<int, std::shared_ptr<D
- 重新分配指针阵列的一部分的安全方法
- 将整数添加到数组值而无需调用它的最安全方法
- 使用括号运算符实现矩阵类的安全方法
- 将空隙动态铸造到类型的安全方法?
- C/通过套接字发送time_t的最安全方法
- 交换两个类实例的最安全方法
- 将uint16_t投射到wchar_t的安全方法
- 从字符串中读取溢出双倍作为'inf'的安全方法
- 期货是检查单个线程完成情况的安全方法吗
- 在C++中动态分配向量的安全方法是什么
- 在C++类中构建互斥保护的线程安全方法
- C++和跳出动态生成代码的安全方法
- 这是实现错误处理的安全方法吗
- 将长整数转换为字符数组的最安全方法是什么
- 缓存 PID 到端口映射窗口的安全方法
- 将无符号长整整除以无符号长整型的最安全方法