轉載自: http://blog.csdn.net/yockie/article/details/8838686
所謂的原子操作,取的就是“原子是最小的、不可分割的最小個體”的意義,它表示在多個線程訪問同一個全局資源的時候,能夠確保所有其他的線程都不在同一時間內訪問相同的資源。也就是他確保了在同一時刻只有唯一的線程對這個資源進行訪問。這有點類似互斥對象對共享資源的訪問的保護,但是原子操作更加接近底層,因而效率更高。 在以往的C++標准中並沒有對原子操作進行規定,我們往往是使用匯編語言,或者是借助第三方的線程庫,例如intel的pthread來實現。在新標准C++11,引入了原子操作的概念,並通過這個新的頭文件提供了多種原子操作數據類型,例如,atomic_bool,atomic_int等等,如果我們在多個線程中對這些類型的共享資源進行操作,編譯器將保證這些操作都是原子性的,也就是說,確保任意時刻只有一個線程對這個資源進行訪問,編譯器將保證,多個線程訪問這個共享資源的正確性。從而避免了鎖的使用,提高了效率。 我們還是來看一個實際的例子。假若我們要設計一個廣告點擊統計程序,在服務器程序中,使用多個線程模擬多個用戶對廣告的點擊: #include <boost/thread/thread.hpp> #include <atomic> #include <iostream> #include <time.h> using namespace std; // 全局的結果數據 long total = 0; // 點擊函數 void click() { for(int i=0; i<1000000;++i) { // 對全局數據進行無鎖訪問 total += 1; } } int main(int argc, char* argv[]) { // 計時開始 clock_t start = clock(); // 創建100個線程模擬點擊統計 boost::thread_group threads; for(int i=0; i<100;++i) { threads.create_thread(click); } threads.join_all(); // 計時結束 clock_t finish = clock(); // 輸出結果 cout<<"result:"<<total<<endl; cout<<"duration:"<<finish -start<<"ms"<<endl; return 0; } 從執行的結果來看,這樣的方法雖然非常快,但是結果不正確 E:\SourceCode\MinGW>thread.exe result:87228026 duration:528ms 很自然地,我們會想到使用互斥對象來對全局共享資源的訪問進行保護,於是有了下面的實現: long total = 0; // 對共享資源進行保護的互斥對象 mutex m; void click() { for(int i=0; i<1000000;++i) { // 訪問之前,鎖定互斥對象 m.lock(); total += 1; // 訪問完成后,釋放互斥對象 m.unlock(); } } 互斥對象的使用,保證了同一時刻只有唯一的一個線程對這個共享進行訪問,從執行的結果來看,互斥對象保證了結果的正確性,但是也有非常大的性能損失,從剛才的528ms變成了現在的8431,用了原來時間的10多倍的時間。這個損失夠大。 E:\SourceCode\MinGW>thread.exe result:100000000 duration:8431ms 如果是在C++11之前,我們的解決方案也就到此為止了,但是,C++對性能的追求是永無止境的,他總是想盡一切辦法榨干CPU的性能。在C++11中,實現了原子操作的數據類型(atomic_bool,atomic_int,atomic_long等等),對於這些原子數據類型的共享資源的訪問,無需借助mutex等鎖機制,也能夠實現對共享資源的正確訪問。 // 引入原子數據類型的頭文件 #include <atomic> // 用原子數據類型作為共享資源的數據類型 atomic_long total(0); //long total = 0; void click() { for(int i=0; i<1000000;++i) { // 僅僅是數據類型的不同而以,對其的訪問形式與普通數據類型的資源並無區別 total += 1; } } 我們來看看使用原子數據類型之后的效果如何: E:\SourceCode\MinGW>thread.exe result:100000000 duration:2105ms 結果正確!耗時只是使用mutex互斥對象的四分之一!也僅僅是不采用任何保護機制的時間的4倍。可以說這是一個非常不錯的成績了。 原子操作的實現跟普通數據類型類似,但是它能夠在保證結果正確的前提下,提供比mutex等鎖機制更好的性能,如果我們要訪問的共享資源可以用原子數據類型表示,那么在多線程程序中使用這種新的等價數據類型,是一個不錯的選擇。