2012-03-13 419 views
18

我正在使用boost:线程库将单线程程序更改为多线程。该程序使用unordered_map作为hasp_map进行查找。我的问题是......unordered_map线程安全

一次有很多线程正在写入,而另一个线程正在读取,但不是同时读取和写入,即所有线程都将读取或全部写入。这将是线程安全的,并为此设计的容器?如果真的如此,它是否真的是并行的,并提高性能?我需要使用一些锁定机制吗?

我在某处读到C++标准所说的行为将会是未定义的,但是这一切吗?

更新:我也在考虑英特尔concurrent_hash_map。这会是一个不错的选择吗?

+2

“但是,所有”...作为UB应该足以不这样做。 – PlasmaHH 2012-03-13 14:02:43

+0

阅读本文http://stackoverflow.com/questions/1362110/is-the-c-stl-stdset-thread-safe – xanatos 2012-03-13 14:03:41

+0

@PlasmaHH如果它是特定于实现的,它可能是,如果您想为此编写代码实现者。如果您为Windows编写代码,Microsoft实施某些方法对您来说可能就足够了。 – xanatos 2012-03-13 14:04:33

回答

36

STL容器的设计,这样可以保证能够有:

A.多个线程在同一时间在同一时间阅读

B.一个线程写入

有多个线程写入不是上述条件之一,是不允许的。多线程写入将因此创建数据竞争,这是未定义的行为。

你可以使用互斥锁来解决这个问题。 shared_mutex(与shared_locks结合)将特别有用,因为该类型的互斥锁允许多个并发读取器。

http://eel.is/c++draft/res.on.data.races#3是保证能够在不同线程上同时使用const函数的标准部分。 http://eel.is/c++draft/container.requirements.dataraces指定了一些在不同线程上安全的非常量操作。

+0

@ EthanSteinberg-std :: mutex?或提升:互斥? – questions 2012-03-13 14:12:31

+0

@questions他们都是一样的。 Boost :: mutex可能更容易使用,因为更多的编译器支持它而不是std :: mutex。 – Lalaland 2012-03-13 14:14:09

+0

@ EthanSteinberg-我不需要对读者有任何锁定,对吧?因为多个线程可以同时读取。 – questions 2012-03-14 00:47:07

5

请问这是线程安全的,并为此设计的容器?

不,标准容器不是线程安全的。

我需要使用一些锁定机制吗?

是的,你这样做。既然你使用了boost,那么boost::mutex将是一个好主意;在C++ 11中,有std::mutex

我在某处读到C++标准所说的行为将会是未定义的,但是这一切吗?

事实上,行为是不确定的。我不确定你的意思是“全部?”,因为未定义的行为是最糟糕的行为类型,而展示它的程序根据定义是不正确的。特别是,不正确的线程同步可能会导致随机崩溃和数据损坏,通常难以诊断,因此您应该不惜一切代价避免它。

更新:我也在想关于英特尔concurrent_hash_map。这会是一个不错的选择吗?

听起来不错,但我从来没有用过它,所以我不能提供意见。

3

现有的答案涵盖的要点:

  • 你必须有一个锁来读取或写入地图
  • 你可以使用多读者/单写锁以提高并发

此外,你应该知道:使用较早retrie

  • VED迭代器或引用或指针在地图中的项目,算作一个读或写操作

  • 写操作在其他线程可能无效的指针/引用/迭代器的图来进行,就像他们,如果他们在同一个线程做了,即使做出了尝试之前继续使用他们再次获得锁...

1

您可以使用concurrent_hash_map或采用一个互斥体,当你访问unordered_map。使用intel concurrent_hash_map的问题之一是你必须包含TBB,但是你已经使用了boost.thread。这两个组件具有重叠功能,因此使您的代码库复杂化。

1

std :: unordered_map符合Container要求(编号http://en.cppreference.com/w/cpp/container/unordered_map)。有关集装箱螺纹安全,请参阅:http://en.cppreference.com/w/cpp/container#Thread_safety

要点:

  • “在同一容器中不同的元素可以同时通过不同的线程被修改”
  • “所有const成员函数可以同时由相同的容器上的不同线程调用另外。 ,成员函数begin(),end(),rbegin(),rend(),front(),back(),data(),find(),lower_bound(),upper_bound(),equal_range() ),除了在关联容器中,operator [],为了线程安全的目的而表现为const(也就是说,它们也可以被同一容器上的不同线程同时调用)。