繁体   English   中英

从另一个线程插入/擦除时,我可以访问C ++ 11 std :: map条目吗?

[英]Can I access a C++11 std::map entry while inserting/erasing from another thread?

我可以访问(不锁定)std :: map条目而另一个线程插入/删除entrys吗?

示例伪C ++:

typedef struct {
   int value;
   int stuff;
}some_type_t;

std::map<char,some_type_t*> my_map;   

//thread 1 does:
my_map.at('a')->value = 1;

//thread 2 does:
some_type_t* stuff = my_map.at('b');

//thread 3 does:
my_map.erase('c');

//I'm not modifying any elements T is a pointer to an previously allocated "some_type_t" 

std C ++ 11说所有成员都应该是线程安全的(erase()不是const)。

没有。是的。

两个或多个线程可以执行const的地图,其中一些非上操作const操作也算(操作返回非const迭代器,因此没有const ,比如begin和类似的东西)。

您还可以修改mapset的元素的非键组件,同时运行其他不读/写/销毁所述元素的非键组件的操作(除了诸如erase=类的东西之外,其中大部分都是这样)。

使用const和类似的map操作(如findat )执行任何操作时,都无法eraseinsert或执行其他类似的非const映射操作。 请注意,如果添加元素, []可以类似于erase

该标准有一个明确的非const操作列表,为了线程安全的目的计算为const - 但它们基本上是返回iterator&查找。

不不不不不!

map::erase使用map::at使用的搜索算法修改地图条目和混乱之间的链接。 您可以在擦除期间使用元素,但不能执行搜索算法本身!

我已经创建了一个插图程序。 在我的机器上,这个程序有时会打印OK,有时会抛出一个地图异常 - 这意味着搜索出错了。 增加读取线程的数量会使异常更频繁地出现。

#include <iostream>
#include <thread>
#include <map>
#include <cassert>

std::map<int, int> m;

// this thread uses map::at to access elements
void foo()
{
  for (int i = 0; i < 1000000; ++i) {
    int lindex = 10000 + i % 1000;
    int l = m.at(lindex);
    assert(l == lindex);
    int hindex = 90000 + i % 1000;
    int h = m.at(hindex);
    assert(h == hindex);
  }
  std::cout << "OK" << std::endl;
}

// this thread uses map::erase to delete elements
void bar()
{
  for (int i = 20000; i < 80000; ++i) {
    m.erase(i);
  }
}

int main()
{
  for (int i = 0; i < 100000; ++i) {
    m[i] = i;
  }

  std::thread read1(foo);
  std::thread read2(foo);
  std::thread erase(bar);

  read1.join();
  read2.join();
  erase.join();

  return 0;
}

No. std :: map不是线程安全的。 英特尔的线程构建块(tbb)库有一些并发容器。 检查tbb

只要线程不同时访问同一个地址就没有问题。

但是对于你的问题的直接答案,不,它不是线程安全的,所以你不能没有锁定没有任何错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM