C++中向量和列表的非写成员函数的线程安全

Thread safety of the non-write member functions of vectors and lists in C++

如果我正在访问 std::vector 或 std::list 的成员函数,它是线程安全的吗?

示例:

struct ABC
{
...
}

std::vector<ABC> vecofAbc;

以下操作是线程安全的吗?

vecofAbc.at(1) ;
ABC::iterator iter = vecofAbc.end();
ABC::iterator iter = vecofAbc.begin();

同样,上面的std::list成员函数是线程安全的吗?

我知道 push_back() 在写入时不会是线程安全的。

读取是线程安全的,只要没有并行写入就不需要同步机制。

读取操作不是线程安全的。如果在执行读取操作时修改容器,则存在数据竞争,并且行为未定义。

读取操作本身不会创建竞争条件,因此多个读取不需要彼此同步 - 仅与修改有关。

如果您可以保证只有对该向量的读取访问权限,那么是的,从多个线程执行此操作是安全的。仅当线程更改某些内容时才会出现问题。

当一个方法不受其他线程同时读取或写入相同数据的影响时,该方法被称为线程安全的。因此,您只阅读的事实实际上是无关紧要的。你提到的方法不是线程安全的,因为如果有第二个线程同时修改向量,你就会有数据竞争。

PS:不过,如果您只从 vector 中读取,则不需要线程安全,因为没有数据争用,一切都很好。

最好不要将 C++ 中的线程安全视为单个操作的 属性,而是相互关联的多个操作的 属性。

vecofAbc.at(1) ;
ABC::iterator iter = vecofAbc.end();
ABC::iterator iter = vecofAbc.begin();

其中每一个都是线程安全的。它们可以出现在单独的线程中,不涉及数据竞争。

有些操作与上述操作不是线程安全的。其中包括

vecofAbc.push_back(some_abc);
vecofAbc.reserve(10000);

还要注意

vecofAbc[0] = some_abc;

相互线程安全
vecofAbc.at(1);

vecofAbc[1] = some_abc;

规则是容器上任意数量的 const 操作都是相互线程安全的,并且 .begin()end() 和许多其他操作(它们不会改变就此规则而言,容器布局)被视为 const

此外,从不同的元素读取 from/writing 与 reading/writing 是相互线程安全的,并且读取 from/writing 与其他 [=15] 元素是相互线程安全的=] 容器上的操作(以及其他被上述规则 视为 const 的操作)。

std::vector 保证在通过 const 方法或通过 视为常量的方法调用自身时,它只会调用 类 上的 const 方法 根据上述规则。如果您的对象的 const 方法不能实现相互线程安全,那么一切都将失败。

有关详细信息,请参阅 Does const mean thread safe