- 问题**
我认为下面的代码应该会导致运行时问题,但实际上并没有。我试图在一个线程中更新shared_ptr
所指向的底层对象,并在另一个线程中访问它。
struct Bar {
Bar(string tmp) {
var = tmp;
}
string var;
};
struct Foo {
vector<Bar> vec;
};
std::shared_ptr<Foo> p1, p2;
std::atomic<bool> cv1, cv2;
void fn1() {
for(int i = 0 ; i < p1->vec.size() ; i++) {
cv2 = false;
cv1.wait(true);
std::cout << p1->vec.size() << " is the new size\n";
std::cout << p1->vec[i].var.data() << "\n";
}
}
void fn2() {
cv2.wait(true);
p2->vec = vector<Bar>();
cv1 = false;
}
int main()
{
p1 = make_shared<Foo>();
p1->vec = vector<Bar>(2, Bar("hello"));
p2 = p1;
cv1 = true;
cv2 = true;
thread t1(fn1);
thread t2(fn2);
t2.join();
t1.join();
}
- 说明**
奇怪的是,输出如下所示。打印新的大小为0(空),但仍然能够访问前一个向量的第一个元素。
0 is the new size
hello
我的理解是,上述代码是不是线程安全的正确?我错过了什么?
或
根据文件
所有成员函数(包括复制构造函数和复制赋值)都可以由shared_ptr的不同示例上的多个线程调用,而不需要额外的同步,即使这些示例是副本并共享同一对象的所有权。
既然我使用的是->
/*
成员函数,这是否意味着代码是线程安全的?这部分有点混乱,因为我同时执行读和写,而没有同步。
1条答案
按热度按时间gwbalxhn1#
至于shared_ptr:一般来说,你可以从多个线程调用shared_ptr的不同示例的所有成员函数,而不需要同步。但是,如果你想从同一个shared_ptr示例上的多个线程调用这些函数,那么可能会导致争用情况。当我们在shrared_ptr的情况下谈论线程安全保证时,如上所述,它仅保证shared_ptr的内部,而不保证底层对象。
话虽如此,考虑一下下面的代码并阅读注解。你也可以在这里玩它:https://godbolt.org/z/8hvcW19q9