c++ - 在单个链表线程中删除和插入是否安全?

标签 c++ linked-list thread-safety singly-linked-list

使用 std::forward_list 在删除插入时是否存在数据竞争?例如,我有一个线程除了在列表末尾添加新元素外什么都不做,而我有另一个线程遍历(相同)列表并可以从中删除元素。

根据我对链表的了解,每个元素都包含一个指向下一个元素的指针,因此如果我删除最后一个元素,同时插入一个新元素,这会导致数据竞争还是执行这些操作容器的工作方式不同(或者它们是否处理这种可能性)?

如果是数据竞争,是否有一种(简单且快速)的方法来避免这种情况? (注意:插入的线程是两者中速度最关键的。)

最佳答案

标准 C++ 库容器有线程安全保证,但它们往往不是人们会考虑的线程安全保证类型(也就是说,然而,人们期望错误的错误)。标准库容器的线程安全保证大致如下(相关章节17.6.5.9 [res.on.data.races]):

  1. 您可以根据需要拥有任意数量的容器读者。 reader 的确切定义有点微妙,但大致相当于 const 的用户。成员函数加上使用一些非 const成员只读取数据(读取数据的线程安全不是容器关心的任何问题,即 23.2.2 [container.requirements.dataraces] 指定可以在容器不引入数据竞争的情况下更改元素)。
  2. 如果容器只有一个写入者,则在另一个线程中不应有其他容器的读取者或写入者。

也就是说,读取容器的一端并写入另一端是不是线程安全的!事实上,即使实际的容器更改不会立即影响读取器,在将一段数据从一个线程传送到另一个线程时,您总是需要某种形式的同步。也就是说,即使您可以保证消费者不会 erase()当前生产者节点 insert() s,会有一场数据竞赛。

关于c++ - 在单个链表线程中删除和插入是否安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20887412/

相关文章:

Java:单线程修改对象,多线程读取

c++ - 在 GDB 启动时禁用名称 demangling

c++ - Qt connect() 用法

c++ - 当存在要复制的值数组时,在 C++ 中重载 = 运算符

java - 为什么 ListIterator 为 LinkedList 中的元素提供索引?

java - 创建链表

c - Del. and r/w linked List Nodes in Multithreading with RW-locks -> 死锁?

c++ - 在 C++ 中将格式化的数值数据读取到数组

java - 如何删除链表中的特定节点

java - 线程转储之间有什么区别