Iterate over STL container using indices safe way to avoid using locks?

空扰寡人 提交于 2020-01-05 05:26:07

问题


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.

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

I understand that iterators can be invalidated by changes to the container but perhaps if we make sure the initial container size is large enough for any future additions, it should also be safe to iterate over the elements without locking reads or writes?


回答1:


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.

Don't, this is not thread safe. Consider a thread that is trying to read a value and goes to the current buffer. At this time a second thread is growing the buffer, and after the first one obtained the pointer to the buffer, but before it actually read the value, the second thread releases the contents of the buffer. The first thread is reading dead objects, which is undefined behavior.

Restricting the problem to a reserve()-ed vector (i.e. avoiding the problem of growing the buffer) the approach is still not thread safe. The code in push_back() will do something similar to:

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;
       }
   }
};

The problem here is that without synchronization mechanisms the compiler can reorder the instructions, increment end and store that to memory, then call the constructor of T over the buffer element. If that reordering happens, then your reader thread might see a value of size() that includes the value that is currently being stored, but the value is not yet in the vector.




回答2:


You should not write code to depend on this as its an implementation detail and is not part of the vector's exported API as far as I know. If its documented behavior, you can rely on it, if it's not then don't do it. Anything that is implementation dependent and not a documented part of the API is subject to change on different platforms and on different versions of your tools on the same platform.

Also, from @GManNickG's comment --> You're going to have a race condition on the invocation of size() as it will be modified and read without locking here.




回答3:


You cannot rely on suggestion about iterators will not be invalidated (cus there is many space left). And you need shared_mutex and shared_lock for this. (example of usage)



来源:https://stackoverflow.com/questions/15370644/iterate-over-stl-container-using-indices-safe-way-to-avoid-using-locks

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!