測試結論是發現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
不過這點性能對現在的計算機來說,應該沒什么影響了。
