Closed. This question is off-topic。它当前不接受答案。
想改善这个问题吗? Update the question,所以它是on-topic,用于堆栈溢出。
5年前关闭。
我对此问题感到困惑,当我查看某人的
例如在C ++中:
定义
如果代码在
如果
使用atomic_increase / atomic_decrease是唯一正确的方法吗?
我认为,它应该在
想改善这个问题吗? Update the question,所以它是on-topic,用于堆栈溢出。
5年前关闭。
我对此问题感到困惑,当我查看某人的
C++
代码时就会出现此问题。例如在C ++中:
// Global var
int g_var = 0;
// thread 1 call Func1() forever:
void Func1() {
++g_var;
}
// thread 2 call Func2() forever:
void Func2() {
--g_var;
}
定义
Func1
通话时间times1
,Func2
通话时间times2
times1 - times2
总是= g_var
吗?如果代码在
C
中而不在C++
中怎么办?如果
g_var
使用volatile
装饰怎么办?使用atomic_increase / atomic_decrease是唯一正确的方法吗?
我认为,它应该在
violatile
中使用C++
,而不必在Windows中像InterlockedIncrement
那样使用原子操作,因为汇编代码只是一行,一条add
指令:mov eax,1
add dword ptr [a],eax
最佳答案
按照出现的顺序回答您的问题:
不,您的程序具有未定义的行为。可能是这样的情况:线程1读取变量(要增加),被中断,然后线程2读取变量(要减少),将其减小并写回(因此与我们开始的值相比减一)然后,线程1继续,增加其记忆的旧值并将其写回到变量中,与我们开始使用的值相比,结果加一。
语言在这里没有任何改变。volatile
仅保证单个线程可能不会缓存变量的值,即++g_var; ++g_var;
将读取变量,增加,写入,读取,增加,写入。优化程序不会将其替换为g_var += 2
。但是线程仍然可以在读写之间中断,这是很危险的部分。
这是您需要原子操作的完美示例。在int
上使用原子操作,或者使用std::atomic<int>
包装器,该包装器在调用常规运算符时自动为您执行此操作,从而使您的代码更具可读性。
只需将int g_var
替换为std::atomic<int> g_var
即可解决任何问题。