如果我创建一个将由两个不同的std :: threads访问的对象,在创建对象或将其传递给线程时是否需要做出任何特殊规定?
例如:
class Alpha
{
public:
int x;
};
void Foo(Alpha* alpha)
{
while (true)
{
alpha->x++;
std::cout << "Foo: alpha.x = " << alpha->x << std::endl;
}
}
void Bar(Alpha* alpha)
{
while (true)
{
alpha->x++;
std::cout << "Bar: alpha.x = " << alpha->x << std::endl;
}
}
int main(int argc, char * argv[])
{
Alpha alpha;
alpha.x = 0;
std::thread t1(Foo, &alpha);
std::thread t2(Bar, &alpha);
t1.join();
t2.join();
return 0;
}
这编译很好,似乎也运行正常。但我没有明确地告诉我的程序,alpha
需要由两个不同的线程访问。我应该这样做吗?
答案 0 :(得分:4)
alpha.x
上有竞争条件,因为两个线程可能会在另一个读取/写入其值时写入。您可以通过将x
的类型更改为std::atomic<int>
或使用互斥锁保护读/写访问权来解决此问题。
答案 1 :(得分:3)
如果一个对象将被多个线程访问,那么您必须为同步做好准备。在您的情况下,将变量x声明为原子就足够了:
#include <atomic>
class Alpha
{
public:
std::atomic<int> x;
};
这将保证任何增加&#34; x&#34;实际上将使用原子fetch_and_add()方法。这保证了每个线程增加变量&#34; x&#34;将获得x的唯一递增值。
在您发布的代码中,如果执行交错恰到好处,则两个线程极有可能获得x的值。