在多线程程序中考虑以下代码:
QString target = remaining.first(); // remaining is a QVector<QString> class
remaining.pop_front();
安全吗?看起来多个线程可能同时使用相同的“目标”。或者检索+删除第一个值的安全方法是什么?
答案 0 :(得分:2)
没有互联网保护代码,不,它根本不安全。
我不详细了解QVector
,但我相信两个线程都可以做到:
QString target = remaining.first();
这只是复制了一个向量的元素,所以每个线程都有自己的QString
对象叫target
,它们是独立的对象(在他们使用的幕后implicit sharing所以不是独立的,但你应该能够treat them as independent)
但是这一行会修改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();
}
}