问题描述
我知道可以从 std::vector
并发读取而不会产生不良"后果,因为该操作可以被认为是线程安全的.
I know that is possible to read concurrently from a std::vector
without "bad" consequences because this operation can be considered thread-safe.
但是对于写操作就不能这样说了.但是,我想知道这是否并不总是正确的,例如考虑到我的特定情况.
But the same cannot be said for writing operations. But, I am wondering if this is not always true, for example considering my particular scenario.
我有一个 std::vector
,其中所有元素都初始化为 false
,并且,给定一个索引数组,我需要更改这些元素的值(每个索引的vector[index]
)从false
到true
.
I have a std::vector<bool>
, where all the elements are initialized to false
, and, given an array of indices, I need to change the value of these elements (vector[index]
for each index) from false
to true
.
如果我为每个索引使用不同的线程(并且有可能某些索引具有相同的值),该操作是否可以被认为是线程安全的?
If I use a different thread for each index (and there is the possibility that some indices have the same value), can this operation be considered thread-safe?
如果向量是 std::vector
(或任何原始类型)并且分配的值始终相同(例如 1),此操作是否仍可被视为线程安全的?
If the vector is a std::vector<int>
(or any primitive type) and the value assigned is always the same (for example 1) can this operation still be considered thread-safe?
推荐答案
并发写入 vector
永远是不行的,因为底层实现依赖于 vector< 类型的代理对象;bool>::reference
就好像它是对 bool 的引用一样,但实际上将根据需要获取和更新位域字节.
Concurrent writes to vector<bool>
are never ok, because the underlying implementation relies on a proxy object of type vector<bool>::reference
which acts as if it was a reference to bool, but in reality will fetch and update the bitfield bytes as needed.
在不同步的情况下使用多个线程时,可能会发生以下情况:线程 1 应该更新一点,并读取包含它的字节.然后线程 2 读取同一个字节,然后线程 1 更新一个位并将该字节写回,然后线程 2 更新另一个位并将该字节写回,覆盖线程 1 的编辑.
When using multiple threads without synchronization, the following might happen: Thread 1 is supposed to update a bit, and reads the byte containing it. Then thread 2 reads the same byte, then thread 1 updates a bit and writes the byte back, and then thread 2 updates another bit and writes the byte back, overwriting the edit of thread 1.
这只是一种可能的情况,还有其他情况会导致相同类型的数据损坏.
This is just one possible scenario, there are others that would lead to the same kind of data corruption.
在vector
的情况下,如果你绝对确定所有线程都将相同的值写入vector中,那么这个操作一般不会导致数据腐败.但是,该标准当然总是格外小心,并将对内存位置的所有并发访问(其中至少一个是写访问)定义为未定义行为:
In the vector<int>
situation, if you are absolutely sure that all threads write the same value into the vector, then this operation will generally not lead to data corruption. However, the standard is of course always extra careful and defines all concurrent accesses to a memory location, of which at least one is a write access, to be undefined behavior:
如果其中一个修改了内存位置而另一个读取或修改了相同的内存位置,则两个表达式计算会发生冲突.——intro.races/2
Two expression evaluations conflict if one of them modifies a memory location and the other one reads or modifies the same memory location. – intro.races/2
因此,一旦您对来自两个不同线程的同一元素进行任何修改操作,您就会遇到竞争条件并需要适当的同步,例如通过使用 std::atomic
.
Therefore, as soon as you do any modification operation on the same element from two different threads, you will have a race condition and need proper synchronization, e.g. by using std::atomic<int>
.
这篇关于同时写入 vector<bool>的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!