我正在用 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()
但我不明白为什么它会成为问题。如果我不断收到数据,我相信无论如何都会消耗整个列表。
最佳答案
没有。
你是对的,但实际上你不能同时从不同线程调用任何容器成员函数并期望它可靠地工作,因为那些成员函数的实现它们本身不是 [保证] 线程安全的。
I don't see why it would be a problem
不公开的,我同意在 std::list
的特殊情况下,我不会对这里的实际问题抱太大期望。一些商店可能认为这是继续并在生产中使用它的充分理由。不过,我不会在代码审查时接受它。关键是我们根本无法*确切地知道内部结构是做什么的。
话虽这么说,如果您有一些特殊的标准库实现(或带有特殊标志/开关/选项的标准库实现)确实提供了这种保证,那么请把自己搞砸 ;) * 最后,您可以检查它的代码并为自己做出决定,但老实说,这是疯狂的谎言!
关于c++ - std::list 可以用于简单的无锁队列吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52294896/