测试结论是发现C++11原子操作在性能上,比以往用到的InterlockedIncrement或__sync_add_and_fetch性能上慢了1倍左右。
另外补充一点,在对原子变量进行比较的时候,最好是引用它操作后的返回值,而不要直接用原子变量进行比较,比如:
下面是测试过程以及代码
std::atomic<long> g_data = 0; long v = ++g_data; if(v = 1000) { dosomething(); } //不要用下面的方式,可能某个线程已将g_data原子的值设置为了1000,而引起不只一个线程执行下面的动作 if(g_data = 1000) { dosomething(); }
以前用到原子操作函数
volatile long Sync_Add(volatile long* value) { #ifdef WIN32 return InterlockedIncrement(value); #else return __sync_add_and_fetch(value, 1); #endif } volatile long Sync_Sub(volatile long* value) { #ifdef WIN32 return InterlockedDecrement(value); #else return __sync_sub_and_fetch(value, 1); #endif }
C++ 11自带原来操作<atomic>
#include <atomic> std::atomic<long> g_data = 0; g_data++; //线程安全的原子操作
测试的源代码如下:
volatile long Sync_Add(volatile long* value) { #ifdef WIN32 return InterlockedIncrement(value); #else return __sync_add_and_fetch(value, 1); #endif } volatile long Sync_Sub(volatile long* value) { #ifdef WIN32 return InterlockedDecrement(value); #else return __sync_sub_and_fetch(value, 1); #endif } long g_data = 0; //std::atomic<long> g_data = 0; void threadfun() { for (int i=0;i<10000;i++) { g_data = Sync_Add(&g_data); //g_data++; } } int main(int argc, char* argv[]) { int start = ::GetTickCount(); for (int i = 0; i < 1000; i++) { std::thread t(threadfun); t.join(); } std::cout<<"g_data = "<< g_data <<" use time = " << ::GetTickCount() - start << std::endl; system("pause"); return 0; }
运行结果:
g_data = 10000000 use time = 1497 //C++11的<atomic> g_data = 10000000 use time = 717 //非C++11
不过这点性能对现在的计算机来说,应该没什么影响了。