C ++的Thread Safe Vector类

时间:2009-07-08 17:39:11

标签: c++ multithreading thread-safety

有没有人知道c ++的快速和脏线程安全矢量类?我正在多线程处理一些代码,我相信我遇到的问题与使用向量的方式有关。我打算重写代码,但在我疯狂重做代码之前,我想用线程安全向量来测试它。我还想知道如果有这样的东西,它会比写我自己的版本容易得多。

6 个答案:

答案 0 :(得分:8)

由于算法,这很难。

假设您包装了vector,以便使用互斥锁序列化其所有成员函数,例如Java同步方法。然后对该向量的std::remove的并发调用仍然不安全,因为它们依赖于查看向量并根据它们看到的内容进行更改。

因此,您的LockingVector需要专门化标准算法中的每个模板,以锁定整个事物。但是其他算法如std::remove_if将在锁定下调用用户定义的代码。一旦有人开始创建对象的向量,就会在幕后默默地执行此操作,这些对象本身会在内部锁定所有方法。

回答你的实际问题:对不起,不,我不知道。为了快速测试您需要的那种,我建议您从以下开始:

template <typename T>
class LockedVector {
    private:
    SomeKindOfLock lock;
    std::vector<T> vec;
};

然后将其作为替换容器放入,并开始实现成员函数(以及成员typedef和运算符),直到它编译为止。如果你的代码中的任何一个代码在向量上使用迭代器的方式很简单,那么你很快就会注意到它是从内到外不能保证线程安全的,如果需要你可以在这些情况下临时更改调用代码来锁定通过公共方法传播。

答案 1 :(得分:6)

您可以查看TBB(例如concurrent_vector)。我从来没有使用它,老实说,我发现将范围保护对象放在访问更容易(特别是如果向量被正确封装)。

答案 2 :(得分:3)

我认为你会发现继续使用std :: vector要容易得多,但要使用某种互斥锁或其他操作系统同步对象来保护并发访问。如果您使用的是互斥锁,那么您肯定也想使用RAII。

答案 3 :(得分:1)

正如Scott Meyers在有效的STL书中解释的那样,通过线程安全容器,您可以期待:

  • 多次读取是安全的
  • 对不同容器的多次写入是安全的。

多数民众赞成。您不能指望许多其他内容(例如对同一容器的多次写入)是线程安全的。如果这就是您想要的,那么您可以查看STLPort。如果没有,那么我看到的唯一选择是在同步对向量的访问的类中包含向量。

答案 4 :(得分:0)

我忘了是谁讨论了这个,但制作线程安全容器的一个策略如下:

  1. 所有类的公共方法都必须锁定向量,如果成功则必须返回一个布尔值(并且它们可能不会成功!)。因此,不要使用f = myvec[i],而是使用if (myvec.tryGet(i, &f)) {...}并相应地实现该类。
  2. 不提供计数方法。用户必须使用迭代器遍历矢量。
  3. 注意:注意迭代。您必须聪明地使用边界检查迭代器来维护一个永不缩小的向量,否则您可能会遇到具有缓冲区溢出类型错误的代码。

    提供“线程安全”向量的蹩脚而简单的方法是只采用标准向量并在每个方法上锁定向量。但是如果你这样做,你仍然可能最终破坏了代码(例如,一个从0迭代到vec.count的循环可能在迭代时有计数变化)。

    提供“线程安全”容器的第二种方法是创建不可变容器(每个方法都返回一个新容器。这绝对是discussed by Eric Lippert。它是C#,但很容易转换为C ++代码,主要是。你'在你使用容器时仍然需要锁定容器,但是当迭代器中断并且什么都不消失时,涉及缓冲区溢出的所有可怕问题。对于具有函数式编程经验的人来说,实现不可变容器可能是相对第二的性质。

答案 5 :(得分:0)

如果您还没有,请考虑使用tbb库中的concurrent_vector。 C ++ STL向量不是线程安全的,所以如果你计划从多个线程修改向量资源,我找到的最简单的解决方案是使用concurrent_vector。