Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/133.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 同时写入向量<;布尔>;_C++_Multithreading_C++11_Vector - Fatal编程技术网

C++ 同时写入向量<;布尔>;

C++ 同时写入向量<;布尔>;,c++,multithreading,c++11,vector,C++,Multithreading,C++11,Vector,我知道可以同时从std::vector读取,而不会产生“坏”的后果,因为这个操作可以被认为是线程安全的 但对于写操作来说,情况并非如此。但是,我想知道这是否总是正确的,例如考虑到我的特定场景 我有一个std::vector,其中所有元素都初始化为false,并且,给定一个索引数组,我需要将这些元素的值(vector[index]对于每个索引)从false更改为true 如果我对每个索引使用不同的线程(有些索引可能具有相同的值),那么这个操作可以被认为是线程安全的吗 如果向量是std::vecto

我知道可以同时从
std::vector
读取,而不会产生“坏”的后果,因为这个操作可以被认为是线程安全的

但对于写操作来说,情况并非如此。但是,我想知道这是否总是正确的,例如考虑到我的特定场景

我有一个
std::vector
,其中所有元素都初始化为
false
,并且,给定一个索引数组,我需要将这些元素的值(
vector[index]
对于每个索引)从
false
更改为
true

如果我对每个索引使用不同的线程(有些索引可能具有相同的值),那么这个操作可以被认为是线程安全的吗


如果向量是
std::vector
(或任何基元类型),并且分配的值始终相同(例如1),那么此操作仍然可以被认为是线程安全的吗?

vector
的并发写入永远不会正常,因为底层实现依赖于类型为
vector::reference
的代理对象,该对象的行为就像是对bool的引用,但实际上会根据需要获取和更新位字段字节

当使用多个线程而不进行同步时,可能会发生以下情况:线程1应该更新一位,并读取包含它的字节。然后线程2读取相同的字节,然后线程1更新一位并写回字节,然后线程2更新另一位并写回字节,覆盖线程1的编辑

这只是一种可能的情况,还有其他可能导致相同类型的数据损坏


vector
情况下,如果您完全确定所有线程都将相同的值写入向量,则此操作通常不会导致数据损坏。然而,标准当然总是格外小心,并将对内存位置的所有并发访问(其中至少有一个是写访问)定义为未定义行为:

如果其中一个修改内存位置,而另一个读取或修改同一内存位置,则两个表达式求值会发生冲突


因此,只要您从两个不同的线程对同一元素执行任何修改操作,就会出现争用条件并需要适当的同步,例如使用
std::atomic

[container.requirements.dataraces]/2说:

尽管有(17.6.5.9)的规定,但当同时修改同一容器中不同元素中所包含对象的内容时,需要实现以避免数据竞争,除了
vector


因此,您可以从不同的线程安全地修改同一标准库容器的不同元素,除了当该容器为
vector

时,并发访问发生时向量的大小是否为常量?@decltype\u auto是,向量的大小保持不变。这在前面已经讨论过。请参阅:那么,给定“索引数组”,具有访问权限的std::VALARY可能是您的sth。但这与您的并发主题无关。@CraigEstey请注意,这个问题更为具体。“在向量情况下,如果您完全确定所有线程都将相同的值写入向量,那么此操作将永远不会导致数据损坏。”–这是不正确的,无论要写入的值是否相同,对同一内存位置的并发写入都会导致未定义的行为。引用自:“如果其中一个修改内存位置,而另一个读取或修改同一内存位置,则两个表达式求值会发生冲突。”澄清一下……这适用于在同一索引中写入相同的值。如果所有线程都写入不同的索引,就像实际问题的一部分一样,内存位置将是分开的,并且没有数据竞争。@ArneVogel啊,当然,标准总是格外小心。。。您当然不会期望
int
在任何系统上都以非原子方式编写。我在回答中引用了这句话nonetheless@FelixDombek如果您依赖于在相关标准中找不到的期望,那么如果这些期望在将来被证明是错误的,那么您的代码将非常糟糕。经历了足够多的痛苦之后,你会认为我们应该开始学习避免它。@FelixDombek-如果我使用一个大小为一个字节(而不是一个字)的“char”或“uint8_t”类型的向量,它会不会是线程安全的