C ++ std :: set线程安全吗?

我有一个关于std :: set的线程安全性的问题。

据我所知,我可以遍历一个集合,并添加/擦除成员,并不会使迭代器无效。

但请考虑以下情况:

  • 线程“A”遍历一组shared_ptr <Type>
  • 线程“B”偶尔会将项目添加到此集合中。

程序运行时,我遇到了段错误,我不知道为什么发生这种情况。 缺乏线程安全的原因是什么?

STL没有内置的线程支持,所以你必须用自己的同步机制来扩展STL代码才能在multithreading环境中使用STL。

例如看这里: 链接文本

由于set是一个容器类MSDN有以下关于容器的线程安全性的说法。

单个对象对于从多个线程读取是线程安全的。 例如,给定一个对象A,同时从线程1和线程2读取A是安全的。

如果单个对象正在被一个线程写入,则必须保护所有对同一线程或其他线程的读写操作。 例如,给定一个对象A,如果线程1正在写入A,则线程2必须被阻止读取或写入A.

即使另一个线程正在读取或写入相同types的不同实例,读取和写入types的一个实例也是安全的。 例如,给定对象A和B是相同types的,如果在线程1中写入A,而在线程2中读取B,则是安全的。

Dinkumware STL文档包含有关该主题的下列段落。 它可能(如文中所示)对大多数实现有效。

对于标准C ++库中定义的容器对象,如STL容器和模板类basic_string的对象,此实现遵循SGI STL中广泛采用的实践:

多个线程可以安全地读取同一个容器对象。 (一个容器对象中有nunprotected可变子对象。)

两个线程可以安全地操作相同types的不同容器对象。 (在容器types中没有不受保护的共享静态对象。)

如果至less有一个线程正在修改对象,则必须防止同时访问容器对象。 (明显的同步原语,例如Dinkum线程库中的同步原语,不会被容器对象所颠覆。)

因此,没有尝试确保容器对象上的primefaces操作是线程安全的; 但是很容易使共享容器对象在适当的粒度级别上是线程安全的。

没有一个STL容器是线程安全的,所以std::set尤其不是。

在你的情况下,这个问题甚至不是真正的线程安全,但是:你只需要在多个线程之间共享一个对象(很好),然后在一个线程中修改它(很好)。 但正如你所说,修改容器使其迭代器失效。 无论这种情况发生在同一个线程还是不同的线程中,都是没有意义的,因为它仍然是一个容器

D'哦! §23.1.2.8规定插入不会使迭代器无效。

简单的解释:如果线程A正在通过容器移动迭代器,它正在查看容器的内部。 如果线程B修改了容器(即使是一个不会使A具有的迭代器失效的操作),线程A也会遇到麻烦,因为B正在与容器内部相关,可能使它们处于(临时)无效状态。 这会导致线程A中的崩溃。

问题不是迭代器本身。 当他们需要容器的数据结构时,为了find你陷入困境的位置。

就那么简单。

是。 处理这种情况的一种方法是让每个线程在访问相同的set对象之前locking一个共享的互斥体。 确保使用RAII技术来locking和解锁互斥锁。

执行插入可能会导致向量重新分配其底层内存,而迭代器仍可能指向以前(但无效)的内存地址,从而导致段错误。