【发布时间】:2018-09-12 12:13:12
【问题描述】:
我在 C++11 中实现了一个多线程应用程序,它使用一个线程来轮询来自 QUdpSocket(QT5 框架)的数据,并使用另一个线程来处理收集的数据。
当套接字检测到传入数据时,会发出ReadyRead() 信号,所有数据报都会从QUdpSocket 中提取并复制到std::list 中。
void SocketWrapper::QueuePendingDatagrams()
{
while (hasPendingDatagrams()) {
int dataSize = pendingDatagramSize();
QByteArray tmpQByte = receiveDatagram().data();
datagramList.push_back(tmpQByte); // see const_data
}
emit newDatagrams(&datagramList);
}
然后在另一个线程中启动消费者并检索列表的第一个元素,直到列表为空。
void Worker::ProcessDatagrams(std::list<QByteArray>* pDatagramList)
{
while (pDatagramList->size() > 0) {
QByteArray tmpDatagram = pDatagramList->front();
pDatagramList->pop_front();
// Process and log the data within the datagram...
}
我的问题是: 由于我总是弹出第一个元素并在最后一个元素之后推送,这种无锁方法是否线程安全?
我可能(并且将会)在数据处理期间向套接字接收更多数据,因此两个线程最终将同时运行。对我来说,似乎唯一可能发生的数据竞争可能会高估DatagramList->size(),但我不明白为什么会出现问题。如果我不断收到数据,我相信无论如何都会消耗整个列表。
【问题讨论】:
-
使用列表有什么特别的原因吗?对我来说看起来像是一个队列,在弹出之前移动数据通常是一件好事。
-
在我看来,它不是重复的,因为在@Swift-FridayPie 的问题中,使用了互斥锁。如果我理解得很好,它会提供答案。列表不能直接由线程共享,因为它可能导致线程损坏。
-
@Bertinchamps 这不是完全相同的问题,但我们通常也使用重复项来表示“您的答案可能会在此处找到”。然而,在这种情况下,它是一种边界,所以我要离开它
-
@OZ17 上榜没有特别的原因。我对 C++ 很陌生,发现该列表可用于 FIFO 处理。我在这里检查了stackoverflow.com/questions/1262808/… 的区别,为了清楚起见,我确实应该使用这种结构。
标签: c++ multithreading list qudpsocket