这样的事情有效:
std::vector<std::vector<int>> data;
std::shared_mutex m;
...
void Resize() {
// AreAllVectorsEmpty: std::all_of(data.begin(), data.end(), [](auto& v) { return v.empty(); }
if (!AreAllVectorsEmpty()) {
m.lock();
if (!AreAllVectorsEmpty()) {
data.resize(new_size);
}
m.unlock();
}
}
我正在检查AreAllVectosEmpty()
,然后如果条件成功,则进行锁定,然后再次检查相同的条件是否进行调整大小。
这是线程安全吗? Resize
仅由一个线程调用,但其他线程操纵data
的元素。
是否要求AreAllVectorsEmpty
具有内存栅栏或获取语义?
编辑:当m.lock
获得Resize
时,其他线程将会阻止。
编辑:我们还假设new_size
足够大以至于重新分配。
编辑:更新shared_mutex的代码。
编辑:AreAllVectorsEmtpy
正在迭代数据向量。没有其他人修改数据向量,但数据[0],数据[1]等由其他线程修改。我的假设是因为data [0]的size变量在vector中并且是一个简单的整数,所以访问data [0] .size(),data [1] .size()等...是安全的。 Resize
主题。 AreAllVectorsEmpty
正在迭代data
并检查vector.empty()
。
答案 0 :(得分:3)
我会使用shared_mutex并使用:
我认为首先检查大小,然后调整大小,是安全的,只要这是修改向量内容的唯一线程。
锁定会自动暗示内存屏障,否则锁定没有多大意义。
答案 1 :(得分:3)
答案完全取决于AreAllVectorsEmpty
的实施方式。
如果它只是检查一个可以原子设置的标志,那么是的,它是安全的。如果它迭代你想要改变的向量(或其他常用的容器),那么不,它是不安全的(迭代器会发生什么,如果向量在内部重新分配???)。
如果执行后者,则需要读/写锁机制,请查看shared mutexes。
然后,您在检查之前获取共享锁,并在修改时获取独占锁。
请注意,如果areAllVectorsEmpty
使用某些独立的数据结构(除了上面提到的原子标志),您可能必须使用单独的互斥来保护这个 。
答案 2 :(得分:2)
标准似乎没有要求这样做,比较http://en.cppreference.com/w/cpp/container#Thread_safety。如果它适用于您的特定编译器和STL?您需要查看来源。但我不会依赖它。
这让我想到了一个问题:你为什么要这样做?出于性能原因?你测量过性能吗?当你在调用AreAllVectorsEmpty
之前锁定时,它真的是一个可衡量的性能影响吗?
答案 3 :(得分:0)
// AreAllVectorsEmpty:std :: all_of(data.begin(),data.end(),[](auto&amp; v){return v.empty(); }
您正在访问内部向量的内部(调用空),同时另一个线程可以将一些元素插入到一个内部向量中 - &gt;数据竞赛