一个简单的例子:
struct A {
int a;
void set_a (int x)
{
... // line-1
... // line-2
this->a = x; // line-3
}
};
...
vector<A> v; // somewhere假设v在线程-1和线程-2中共享。v.set_a()总是在线程-1中调用,v.push_back()在线程-2中调用.因此,不存在线程安全问题。
下面的事件序列发生了什么:
v.set_a()。push_back(),resize(),.)v必须移动到其他位置这会导致不明确的行为吗?如果是,那么对于这样的场景,最优雅的解决方案是什么?
发布于 2012-07-05 07:26:55
标准(C++11和以前的Posix)对此非常清楚。您正在修改一个线程中的对象(向量),并从多个线程访问它,因此必须保护所有访问,包括读取访问。(至少我想。如果v.set_a()有std::vector<A>类型,那么它不是合法的;我猜您指的是v[i].set_a()或类似的东西。)
这里我不确定标准的确切措辞,但我假设“修改向量”只意味着改变其大小的操作,而不是修改单个成员的操作。因此,像一个线程中的v[0] = x和另一个线程中的v[1]这样的东西,在没有同步的情况下是合法的。但是,对向量中任何对象的所有访问都是对向量的访问,因此,如果向量的大小发生变化,则必须保护对向量中对象的所有访问。这包括“延迟”访问,因为您保存了v[]返回的引用:给定如下内容:
int& ri = v[i];
// ...
doSomethingWithRi(ri);如果任何线程正在修改向量,则必须保护整个代码块。
发布于 2012-07-05 05:53:37
没有什么可以说向量大小是线程安全的,所以我们必须假设它不是,在您的例子中,我肯定会遇到问题,因为您依赖于许多非原子操作。一个优雅的解决方案就是简单地将它封装在一个线程安全版本中。
https://stackoverflow.com/questions/11338449
复制相似问题