C++并发写入数组(而不是std :: vector)bools
我正在使用C++ 11,并且我知道由于std::vector
对bools的专门化,并发写入到std::vector<bool> someArray
不是线程安全的。C++并发写入数组(而不是std :: vector)bools
我试图找出是否写入bool someArray[2048]
有同样的问题:
- 假设在
someArray
所有条目初始设置为假。 - 假设我有一堆线程在
someArray.
的不同索引处写入实际上,这些线程只将假的到的不同数组条目设置为true。 - 假设我有一个阅读器线程,在某个时间点获取一个锁,触发内存围栏操作。
问:将读者看到所有的写操作someArray
被收购的锁之前发生的?
谢谢!
您应该使用std::array<bool, 2048> someArray
而不是bool someArray[2048];
。如果您使用的是C++ 11版本,则需要尽可能多地更新代码。
std::array<bool, N>
与std::vector<bool>
相同,因此在原始安全性方面没有问题。
至于你的实际问题:
将读者看到所有的写操作
someArray
被收购的锁之前发生的?
只有当作家到阵列还与锁交互,无论是在他们写完的时候释放它,或者通过更新与锁读者然后同步关联的值。如果编写者从不与锁进行交互,那么读取器将检索的数据是未定义的。
有一件事你还需要牢记:虽然它并不不安全有多个线程写入同一阵列,前提是它们都写入唯一存储器地址,写作可以很慢通过与高速缓存的交互显着。例如:
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被选为一个例子,但它可能不代表实际的潜在性能差异)。这两个函数应该有相同的结果,但其中一个会比另一个快得多。
首先,一般std :: vector不像您想象的那样是线程安全的。该担保已经规定here。
解决您的问题:读者可能会在而不是获取锁后看到所有写入。这是由于这样的事实,即写入者可能永远不会执行释放操作,该操作是在写入和随后的读取之间建立发生关系之前所需的释放操作。用(非常)简单的术语来说:每个获取操作(例如互斥锁)都需要一个释放操作来同步。任何释放到某个可见元素之前完成的内存操作对于获取相同变量的任何线程都是可见的。另见Release-Acquire ordering。
要清楚,匹配锁定互斥锁时固有的获取操作是解锁操作中固有的释放操作。*表示相同的互斥锁*。即这两个操作通过对互斥体的地址进行rendezvousing来建立排序。释放/获取部分也可以在bools数组上使用atomic_store和atomic_load来建立,尽管避免竞争仍然需要某种形式的静音。 –
谢谢!发布获取顺序实际上很好知道。但是,似乎'std :: vector
要注意的一件重要的事情是int32大小的变量(如bool)上的所有操作(获取和存储)都是原子的(x86或x64体系结构都适用)。所以如果你声明你的数组是volatile(必要的,因为每个线程可能有一个缓存的数组值),你不应该在修改数组时有任何问题(通过多线程)。
如果您需要线程安全性,请使用['std :: atomic_bool'](http://en.cppreference.com/w/cpp/atomic/atomic)并将其称为完成 – Mgetz