c++ - 使用索引安全方式迭代 STL 容器以避免使用锁?

标签 c++ performance stl locking

想知道以下列方式迭代 STL 容器(如 vector )是否安全以避免锁定读/写,但仅允许任何“写入”线程进行 push_back() 操作。

for (size_t i = 0; i < vec.size(); i++)
{
   const T& t = *vec[i];
   // do something with t
}

我知道迭代器可能会因容器的更改而失效,但也许如果我们确保初始容器大小足以容纳任何 future 的添加,那么在不锁定读取或写入的情况下迭代元素也应该是安全的?

最佳答案

Wondering if it's safe to iterate over a STL container such as a vector in the following manner to avoid locking on reads/writes but allowing for push_back() operations only by any "writing" threads.

不要,这不是线程安全的。考虑一个试图读取值并转到当前缓冲区的线程。此时第二个线程正在增长缓冲区,在第一个线程获得指向缓冲区的指针之后,但在它实际读取值之前,第二个线程释放缓冲区的内容。第一个线程正在读取死对象,这是未定义的行为。

将问题限制在 reserve() vector (即避免缓冲区增长的问题)中,该方法仍然不是线程安全的。 push_back() 中的代码将执行类似以下操作:

template <...>
class vector {
   T *begin,*end,*capacity;   // common implementation uses 3 pointers

   void push_back(T value) {
       if (end == capacity) { /* grow vector and insert */ }
       else {
          new (end) T(value);
          ++end;
       }
   }
};

这里的问题是,如果没有同步机制,编译器可以重新排序指令,递增 end 并将其存储到内存中,然后在缓冲区元素上调用 T 的构造函数.如果发生重新排序,那么您的阅读器线程可能会看到 size() 的值,其中包括当前正在存储的值,但该值尚未在 vector 中。

关于c++ - 使用索引安全方式迭代 STL 容器以避免使用锁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15370644/

相关文章:

javascript - 而 x for at javascript

c++ - 修改标准 STL 容器以支持通用队列接口(interface)

c++ - STL 删除没有按预期工作?

c++ - 使用 unordered_map,其中 Key 是 T 的成员

c++ - Qi Symbols 性能慢?

c++ - 从 plasmoid qml 调用 c++ 槽

C++ - 关于多线程的问题

c++ - 如何从dicom文件读取二进制数据?

c++ - 是否可以在正则表达式中命名子模式,然后通过 C++ 中的子模式名称提取匹配项?

performance - 程序在几台计算机上运行缓慢