我知道可以从std::vector
同时读取没有“坏”的后果,因为这个操作可以被认为是线程安全的。
但是写作操作也不能说。但是,我想知道这是否总是如此,例如考虑我的特定情况。
我有一个std::vector<bool>
,其中所有元素都被初始化为false
,并且,给定一个索引数组,我需要更改这些元素的值(vector[index]
索引)从false
到true
。
如果我为每个索引使用不同的线程(并且某些索引可能具有相同的值),是否可以将此操作视为线程安全的?
如果向量是std::vector<int>
(或任何基本类型)并且赋值的值始终相同(例如1),此操作仍然可以被认为是线程安全的吗?
答案 0 :(得分:16)
对vector<bool>
的并发写入永远不会正常,因为底层实现依赖于vector<bool>::reference
类型的代理对象,其行为就好像它是对bool的引用,但实际上它将获取并更新根据需要使用位字节字节。
在没有同步的情况下使用多个线程时,可能会发生以下情况:线程1应该更新一位,并读取包含它的字节。然后线程2读取相同的字节,然后线程1更新一位并将字节写回,然后线程2更新另一位并写回字节,覆盖线程1的编辑。
这只是一种可能的情况,还有一些会导致同样的数据损坏。
在vector<int>
情况下,如果您绝对确定所有线程都将相同的值写入向量,则此操作通常不会导致数据损坏。但是,标准当然总是格外小心,并定义了对内存位置的所有并发访问,其中至少有一个是写访问,是未定义的行为:
如果其中一个修改内存位置而另一个读取或修改相同的内存位置,则两个表达式评估会发生冲突。 - intro.races/2
因此,只要对来自两个不同线程的同一元素进行任何修改操作,就会出现竞争条件并需要正确同步,例如:使用std::atomic<int>
。
答案 1 :(得分:11)
[container.requirements.dataraces] / 2说:
尽管如此(17.6.5.9),当同时修改同一容器中除
vector<bool>
之外的不同元素中的所包含对象的内容时,需要实现以避免数据争用。
因此,当容器为vector<bool>
时,您可以安全地从不同的线程 修改同一标准库容器的不同元素。