考虑多线程程序中的以下代码:
QString target = remaining.first(); // remaining is a QVector<QString> class
remaining.pop_front();
会安全吗?看起来多个线程可能同时使用相同的“目标”。或者检索+擦除第一个值的安全方法是什么?
如果没有保护该代码的互斥锁,不,它根本不安全。
我不知道QVector
详细信息,但我相信两个线程都可以这样做:
QString target = remaining.first();
这只是复制向量的一个元素,因此每个线程都有自己的QString
对象被调用target
并且它们是独立的对象(在幕后它们使用隐式共享所以不是独立的,但你应该能够将它们视为独立的)
但是这一行修改了QVector
:
remaining.pop_front();
这意味着两个线程在没有任何同步的情况下修改同一个对象。remaining.first()
如果在第二个线程调用时第一个线程仍在通过调用访问向量,pop_front()
则存在数据竞争,行为未定义。
同样,如果两个线程pop_front()
同时调用,它们都将尝试删除第一个元素,那里发生的事情是完全不可预测的。您可能会删除一个或两个元素,或者一个元素都没有,或者立即使整个程序崩溃。作为另一种可能性,考虑如果向量只有一个元素会发生什么。两个线程都检查它不是空的,复制first()
元素,然后调用pop_front()
,当只有一个元素时它会尝试删除两个元素。你的程序坏了。
安全的方法是使用互斥锁保护代码,其中mutex
一些全局变量或其他共享变量对两个线程都是可见的:
QString target;
{
QMutexLocker locker(&mutex);
if (!remaining.empty())
{
target = remaining.first();
remaining.pop_front();
}
}