如果我先执行()然后pop_front(),它仍然是线程安全的吗?

时间:2012-10-18 01:34:05

标签: stl qt4

在多线程程序中考虑以下代码:

    QString target = remaining.first(); // remaining is a QVector<QString> class
    remaining.pop_front();

安全吗?看起来多个线程可能同时使用相同的“目标”。或者检索+删除第一个值的安全方法是什么?

1 个答案:

答案 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();
  }
}