C++ 的线程安全向量类
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1099513/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Threadsafe Vector class for C++
提问by ras2124
Does anyone know a quick and dirty threadsafe vector class for c++? I am multithreading some code, and I believe the problem I have is related to the way the vectors are used. I plan to rewrite the code, but before I go crazy redoing the code, I would like to test it with a threadsafe vector to be sure. I also figure if such a thing is out there, it would be much easier than writing my own version.
有谁知道 C++ 的快速而肮脏的线程安全向量类?我正在对一些代码进行多线程处理,我相信我遇到的问题与向量的使用方式有关。我打算重写代码,但在我疯狂地重做代码之前,我想用一个线程安全向量来测试它以确保。我也想如果有这样的东西存在,它会比编写我自己的版本容易得多。
采纳答案by Steve Jessop
This is difficult because of algorithms.
由于算法,这很困难。
Suppose you wrapped vector so that all its member functions are serialised using a mutex, like Java synchronized methods. Then concurrent calls to std::remove
on that vector still wouldn't be safe, because they rely on looking at the vector and changing it based on what they see.
假设您包装了 vector,以便它的所有成员函数都使用互斥锁进行序列化,就像 Java 同步方法一样。然后std::remove
对该向量的并发调用仍然不安全,因为它们依赖于查看向量并根据所看到的内容对其进行更改。
So your LockingVector would need to specialize every template in the standard algorithms, to lock around the whole thing. But then other algorithms like std::remove_if
would be calling user-defined code under the lock. Doing this silently behind the scenes is a recipe for locking inversion as soon as someone starts creating vectors of objects which themselves internally take locks around all their methods.
因此,您的 LockingVector 需要专门化标准算法中的每个模板,以锁定整个事物。但是其他算法std::remove_if
会在锁下调用用户定义的代码。一旦有人开始创建对象的向量,这些对象本身在内部对所有方法进行锁定,那么在幕后默默地这样做是锁定反转的一个秘诀。
In answer to your actual question: sorry, no, I don't know of one. For a quick test of the kind you need, I recommend that you start out with:
回答您的实际问题:抱歉,不,我不知道一个。为了快速测试您需要的类型,我建议您从以下内容开始:
template <typename T>
class LockedVector {
private:
SomeKindOfLock lock;
std::vector<T> vec;
};
Then drop it in as a replacement container, and start implementing member functions (and member typedefs, and operators) until it compiles. You'll notice pretty quickly if any of your code is using iterators on the vector in a way which simply cannot be made thread-safe from the inside out, and if need be you can temporarily change the calling code in those cases to lock the vector via public methods.
然后将其作为替换容器放入,并开始实现成员函数(以及成员 typedef 和运算符),直到它编译为止。您会很快注意到是否有任何代码在向量上使用迭代器,而这种方式根本无法从内到外成为线程安全的,如果需要,您可以在这些情况下临时更改调用代码以锁定通过公共方法向量。
回答by Todd Gardner
You can check out TBB(like concurrent_vector). I've never used it though, honestly, I find putting the scope guard objects around access easier (especially if the vector is properly encapsulated).
您可以查看TBB(如concurrent_vector)。我从来没有用过它,老实说,我发现将范围保护对象放在访问周围更容易(特别是如果向量被正确封装)。
回答by Brian Neal
I think you'll find it far easier to continue to use std::vector, but to protect concurrent access using some kind of mutex or other operating system synchronization object. You'll also definitely want to use RAII if you are using a mutex.
我认为您会发现继续使用 std::vector 容易得多,但使用某种互斥锁或其他操作系统同步对象来保护并发访问。如果您使用互斥锁,您肯定也想使用 RAII。
回答by Naveen
As Scott Meyers explains in the effective STL book, by a thread safe container you can expect that:
正如 Scott Meyers 在有效 STL 书中解释的那样,通过线程安全容器,您可以预期:
- Multiple reads are safe
- Multiple writes to different containers are safe.
- 多次读取是安全的
- 对不同容器的多次写入是安全的。
Thats all. You can not expect many other things such as multiple writes to the same container be thread safe. If this is all what you want then you can take a look at STLPort. If not then the only option I see is to contain the vector in a class that synchronizes the access to the vector.
就这样。您不能期望许多其他事情(例如对同一容器的多次写入)是线程安全的。如果这就是你想要的,那么你可以看看STLPort。如果不是,那么我看到的唯一选择是将向量包含在同步对向量的访问的类中。
回答by Brian
I forget who discussed this, but one strategy for making a thread-safe container is as follows:
我忘记谁讨论过这个了,但是制作线程安全容器的一种策略如下:
- All your class's public methods must lock the vector, and must return a boolean for if they succeeded (and they might not succeed!). So instead of using
f = myvec[i]
, useif (myvec.tryGet(i, &f)) {...}
and implement the class accordingly. - Do not provide a count method. Users must use iterators to traverse the vector.
- 你的类的所有公共方法都必须锁定向量,并且必须返回一个布尔值,如果它们成功(它们可能不会成功!)。因此,不要使用
f = myvec[i]
,而是相应地使用if (myvec.tryGet(i, &f)) {...}
和实现该类。 - 不提供计数方法。用户必须使用迭代器来遍历向量。
Note: Be careful with iteration. You must be clever about maintaining a never-shrinking vector with bounds-checking iterators or you might have code that has buffer-overflow type errors.
注意:注意迭代。您必须聪明地使用边界检查迭代器维护永不收缩的向量,否则您的代码可能存在缓冲区溢出类型错误。
The lame and easy way to provide a "thread-safe" vector is to just take a standard vector and lock the vector on every method. But if you do this, you could still end up with broken code (e.g. a loop that iterates from 0 to vec.count may have count change while it is iterating).
提供“线程安全”向量的笨拙而简单的方法是仅采用标准向量并在每个方法上锁定向量。但是如果你这样做,你仍然可能以损坏的代码结束(例如,从 0 到 vec.count 迭代的循环在迭代时可能会改变计数)。
A 2nd means of providing "thread-safe" containers is to create immutable containers (every method returns a new container. This was definitely discussed by Eric Lippert. It's C#, but easily translates to C++ code, mostly. You'll still need to lock the container when you use it, but all the scary issues involving buffer overflows when iterators break and whatnot go away. Implementing an immutable container is probably relatively 2nd nature to those who are experienced with functional programming.
提供“线程安全”容器的第二种方法是创建不可变容器(每个方法都返回一个新容器。Eric Lippert肯定讨论过这一点。它是 C#,但大多数情况下很容易转换为 C++ 代码。您仍然需要当你使用它时锁定容器,但是当迭代器中断时所有涉及缓冲区溢出的可怕问题以及诸如此类的东西都没有消失。对于那些有函数式编程经验的人来说,实现一个不可变的容器可能是相对的第二本性。
回答by yohannes
If you haven't already, consider using concurrent_vector from the tbblibrary. C++ STL vectors are not thread safe so if you plan on modifying vector resource from multiple threads, the easiest solution i found is to use concurrent_vector.
如果您还没有,请考虑使用tbb库中的concurrent_vector。C++ STL 向量不是线程安全的,因此如果您计划从多个线程修改向量资源,我发现的最简单的解决方案是使用 concurrent_vector。