【问题标题】:Iterator on a vector invalidated if another thread pushes an element on the end the vector?如果另一个线程将元素推到向量的末尾,则向量上的迭代器无效?
【发布时间】:2013-08-23 01:20:40
【问题描述】:

我想知道在这种情况下是否需要互斥锁。

我有一个由两个线程操作的向量my_vector

线程 1:

my_vector.push_back(element)
// send a request for the element, the subject of which thread 2 will receive
// continues

线程 2:

// receive element
iter = my_vector.find(element) // This **will** be found in the vector
// do stuff using iter

我的问题是:线程 1 可能会向 my_vector 添加更多元素,而线程 2 正在使用 iter... 但这有关系吗?如果只在vector的末尾添加item,那么查看中间元素的迭代器肯定不会受到影响吗?

感谢您对此的任何想法。

【问题讨论】:

  • 如果 push_back 导致向量超出其容量,向量将重新分配到一个新的、更大的缓冲区,移动旧数据,然后删除旧缓冲区。因此,如果发生这种情况,您的旧迭代器会指向已删除的数据。

标签: c++ multithreading vector mutex


【解决方案1】:

如果一个对象可以在一个线程中访问而在另一个线程中被修改,则您需要使用锁。

但这应该重要吗?如果只在vector的末尾添加item,那么查看中间元素的迭代器肯定不会受到影响吗?

不要这样推理。它只会引起痛苦。坚持那些保证有效的事情,而不是做你认为应该有效的事情,因为你想不出任何可能出错的方法。一个明显的例子——如果push_back 调整向量的大小会怎样?

【讨论】:

    【解决方案2】:

    很可能最终会受到影响。

    向量通过移动内存来工作。每当您将元素添加到内存已满的向量时,首先将现有元素复制到新分配的更大内存中,然后添加该元素。然后原始内存被破坏。所以任何指向原始内存的迭代器都会失效。

    【讨论】:

    • 我没有意识到向量是这样“调整大小”的。我现在理解 Schwartz 先生的合理建议,即在同时访问方面转向谨慎/锁定方面。谢谢。
    • @ricky116 没问题。请注意,向量的这种行为是因为需要在内存中连续保存元素。调整大小不会发生在例如链表。
    • @maditya - 但是添加到链表会修改内部指针,这会破坏另一个线程的读取。如果一个线程修改了一个对象的内容,而另一个线程正在读取或修改同一个对象,那么您就有了数据竞争,并且程序的行为是未定义的。
    • @PeteBecker 您当然是对的,当涉及多个线程时,必须同步访问以防止数据竞争,而不管容器如何。需要明确的是,我指出的向量和列表之间的区别(即,将元素添加到向量可能会导致向量的其他元素的迭代器无效,但列表不是这种情况)适用于 顺序程序。
    猜你喜欢
    • 1970-01-01
    • 2021-01-23
    • 1970-01-01
    • 2016-08-20
    • 1970-01-01
    • 1970-01-01
    • 2015-04-21
    • 2017-08-29
    • 2020-09-09
    相关资源
    最近更新 更多