静态局部变量的线程安全递增

8
void foo() {
    static int id = 0;
    const int local_id = id++;
    //do something with local_id;
}

多个线程可以并行多次调用foo函数。我希望每次调用foo时都使用“唯一”的local_id值。以上代码是否可行?我想知道第二个线程在第一个线程增加值之前是否将id的值分配给了local_id。如果不安全,是否有标准解决方案?


10
使用 std::atomic_int - Mgetz
请注意,id的初始化可能是线程安全的,也可能不是,这取决于您的编译器是否支持“魔法静态变量”。 - dlf
@dlf 对,但值得一提的是,“魔术静态变量”是C++11所必需的,因此这是编译器符合性的问题,而不是支持可选功能的问题。 - Angew is no longer proud of SO
@Agnew,没错,但问题并没有指出C++11 :). 现在已经太晚了无法编辑,否则我会修改它以表明“无论您是否拥有支持魔术静态变量的C++11编译器”。 - dlf
这真的是C++11吗?对我来说更像是C。 - Wolf
2个回答

10

你的代码不是线程安全的,因为多个线程可以同时读取id,并生成相同值的local_id

如果你想要一个线程安全的版本,可以使用C++11中提供的std::atomic_int

void foo() {
    static std::atomic_int id;
    const int local_id = id++;
    //do something with local_id;
}

3
请注意,如果你正在使用微软编译器,id的初始化将不是线程安全的,因为它们尚未支持“magic statics”(截至VS2013)。换句话说,如果foo从未被调用,然后两个线程同时调用它,id的构造函数可能会并行运行两次,并产生不可预测的结果。 - dlf

0
你的代码不是线程安全的,因为两个线程可能在同一时间内递增 id。
使用互斥锁或 std::atomic 来处理共享的 id 变量。

1
在上述情况下,如何使用互斥?您能否再详细解释一下? - Wolf
将静态内容封装在一个类中,并提供获取/增加方法,在执行操作之前获取互斥锁。 - Claudio

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接