问题描述
如果我有一个函数只对全局向量执行 emplace_back 或 push_back,并将 unique_ptr 作为值,它是线程安全的还是我必须使用互斥锁?互斥量是确保线程安全的唯一方法吗?
void (T param)
{
globalVector.emplace_back(std::make_unique<T>(param));
//or globalVector.push_back (std::make_unique<T>(param));
}
如果它只是 T 的向量?
void (T param)
{
globalVector.emplace_back(param);
//or globalVector.push_back (param);
}
解决方法
是否是线程安全的
没有
还是我必须使用互斥锁?
是的
有关标准容器的线程安全性,请参阅 cppreference。
,考虑这个玩具示例,它说明了例如 vector<int>::push_back
可能执行的关键部分:
struct broken_toy_vector {
size_t size;
size_t capacity;
int* data;
void push_back(int x){
if (size+1 > capacity) {
int* temp = new int[size+1];
// copy from data to temp
temp[size] = x;
size += 1;
delete data;
data = temp;
} else {
throw "not implemented";
}
}
};
A std::vector
肯定不是 broken_toy_vector
,但是当新大小超过当前容量时,向量需要重新分配。 std::vector
没有充分的理由使 push_back
线程安全,因为这会在任何单线程使用中产生开销。此外,对于多个线程,通常您不希望在最低级别进行同步。考虑:
for (int i=0; i<1000; ++i) {
vect.push_back(i);
}
在每次迭代中锁定互斥锁会非常浪费。
TL;博士
没有。从不同线程并发调用 std::vector::push_back
是不安全的。保护对其数据的任何访问的容器的用途有限,因为用户无法控制锁定的粒度。