我正在使用 C++11,并且我知道并发写入 std::vector<bool> someArray
由于 std::vector
的特殊化,它们不是线程安全的对于 bool 值。
我试图找出是否写入 bool someArray[2048]
有同样的问题:
- 假设
someArray
中的所有条目最初设置为false。 - 假设我有一堆线程在
someArray.
中的不同索引处写入事实上,这些线程仅设置从 false 到 true 的不同数组条目。 - 假设我有一个读取器线程,它在某个时刻获取锁,从而触发内存栅栏操作。
问:读者会看到对 someArray
的所有写入吗?在获取锁之前发生了什么?
谢谢!
最佳答案
您应该使用std::array<bool, 2048> someArray
,不是bool someArray[2048];
。如果您使用 C++11,您将希望尽可能地现代化您的代码。
std::array<bool, N>
与 std::vector<bool>
的特化方式不同是的,所以在原始安全方面不存在任何问题。
至于你的实际问题:
Will the reader see all the writes to
someArray
that occurred before the lock was acquired?
仅当数组的写入者也与锁进行交互时,要么在完成写入时释放锁,要么更新与读取器随后同步的锁关联的值和。如果写入者从不与锁交互,则读取器将检索的数据是未定义的。
您还需要记住一件事:虽然让多个线程写入同一个数组并不不安全,只要它们都写入唯一的内存地址,与缓存的交互可能会大大减慢写入速度。例如:
void func_a() {
std::array<bool, 2048> someArray{};
for(int i = 0; i < 8; i++) {
std::thread writer([i, &someArray]{
for(size_t index = i * 256; index < (i+1) * 256; index++)
someArray[index] = true;
//Some kind of synchronization mechanism you need to work out yourself
});
writer.detach();
}
}
void func_b() {
std::array<bool, 2048> someArray{};
for(int i = 0; i < 8; i++) {
std::thread writer([i, &someArray]{
for(size_t index = i; index < 2048; index += 8)
someArray[index] = true;
//Some kind of synchronization mechanism you need to work out yourself
});
writer.detach();
}
}
详细信息将根据底层硬件的不同而有所不同,但在几乎所有情况下,func_a
将比 func_b
快几个数量级,至少对于足够大的数组大小(选择 2048 作为示例,但它可能不能代表实际的底层性能差异)。两个函数应该具有相同的结果,但其中一个函数将比另一个函数快得多。
关于C++ 并发写入 bool 数组(不是 std::vector),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46717870/