如果我们在源文件(.cpp)中定义静态全局变量,
// variable defined in cpp
static std::atomic<double> fps = -1.0;
static std::atomic<BOOL>isSysUp = FALSE;//WinAPI boolean
static std::atomic<bool> isMessaginDone = false;
void foo()
{
while(isSysUp && isMessaginDone ) // with seq.consistent memory order
{
//.... some code //
sleep(1ms);
}
}
void bar()
{
if(isSysUp )
{
if(/.. condition ../ )
{
isMessaginDone = false;
}
}
}
void termi()
{
isSysUp = false;
}
此处 foo 使用主线程调用,其他函数使用子线程调用。
假设函数 foo 调用每个 10ms 的周期,就像 游戏循环 一样。 将 std :: atomic 与静态内部关联一起使用,并执行加载和商店 memory_order_seq_cst 中的操作会降低性能吗?并且不安全?
使用 std :: store(std :: memory_order_release) , std :: load(std :: memory_order_acquire)<是明智的吗? / em> 以上情况通过线程安全获得性能?
(因为在函数 foo 中只读取原子bool而不是在函数 bar 中编写一次的 TERMI )
答案 0 :(得分:2)
在编译单元中使用静态原子与在编译单元中使用静态全局变量一样糟糕或必要。
性能问题可能源于瓶颈。但这与线程和一致性要求之间的共享变量的使用更相关,而不是微妙的内存排序问题。
虽然这是依赖于实现的,但是简单基本类型(如bool或int)上的原子通常是在支持原子CPU指令的情况下实现的,因此可能根本没有性能问题。
例如,根据您的定义:
while (!isMessaginDone)
将被翻译成
movzx eax, BYTE PTR isMessaginDone[rip] ; already atomic CPU instruction
test al, al
和
之类的设置 isMessaginDone=true;
会变成
mov BYTE PTR isMessaginDone[rip], 1
mfence ; compiler is taking care of the memory ordering
另一方面,实现可以自由地使用基于锁的原子实现(例如,使用信号量等),这将需要进行costy OS调用。但在这种情况下,使用内存排序欺骗不会改变CPU调用的成本,也不会带来您期望的性能提升。
所以不要为了过早优化而迷失方向。使用原子,查看asm,如果需要,执行基准测试。