C++11并發(fā)編程關(guān)于原子操作atomic的代碼示例
一:概述
項目中經(jīng)常用遇到多線程操作共享數(shù)據(jù)問題,常用的處理方式是對共享數(shù)據(jù)進(jìn)行加鎖,如果多線程操作共享變量也同樣采用這種方式。
為什么要對共享變量加鎖或使用原子操作?如兩個線程操作同一變量過程中,一個線程執(zhí)行過程中可能被內(nèi)核臨時掛起,這就是線程切換,當(dāng)內(nèi)核再次切換到該線程時,之前的數(shù)據(jù)可能已被修改,不能保證原子操作。
C++11提供了個原子的類和方法atomic,保證了多線程對變量原子性操作,相比加鎖機(jī)制mutex.lock(),mutex.unlock(),性能有幾倍的提升。
所需頭文件<atomic>
二:錯誤代碼
//全局變量
int g_num = 0;
void fun()
{
for (int i = 0; i < 10000000; i++)
{
g_num++;
}
return ;
}
int main()
{
//創(chuàng)建線程1
thread t1(fun);
//創(chuàng)建線程2
thread t2(fun);
t1.join();
t2.join();
cout << g_num << endl;
getchar();
return 1;
}
應(yīng)該輸出結(jié)果20000000,實際每次結(jié)果都不一樣,總是小于該值,正是由于多線程操作同一變量而沒有保證原子性導(dǎo)致的。
三:加鎖代碼
//全局變量
int g_num = 0;
mutex m_mutex;
void fun()
{
for (int i = 0; i < 10000000; i++)
{
m_mutex.lock();
g_num++;
m_mutex.unlock();
}
return ;
}
int main()
{
//獲取當(dāng)前毫秒時間戳
typedef chrono::time_point<chrono::system_clock, chrono::milliseconds> microClock_type;
microClock_type tp1 = chrono::time_point_cast<chrono::milliseconds>(chrono::system_clock::now());
long long time1 = tp1.time_since_epoch().count();
//創(chuàng)建線程
thread t1(fun);
thread t2(fun);
t1.join();
t2.join();
cout << "總數(shù):" << g_num << endl;
//獲取當(dāng)前毫秒時間戳
microClock_type tp2 = chrono::time_point_cast<chrono::milliseconds>(chrono::system_clock::now());
long long time2 = tp2.time_since_epoch().count();
cout << "耗時:" << time2 - time1 << "ms" << endl;
getchar();
return 1;
}
執(zhí)行結(jié)果:多次測試輸出均為20000000,耗時在3.8s左右

四:atomic原子操作代碼
//全局變量
atomic<int> g_num = 0;
void fun()
{
for (int i = 0; i < 10000000; i++)
{
g_num++;
}
return ;
}
int main()
{
//獲取當(dāng)前毫秒時間戳
typedef chrono::time_point<chrono::system_clock, chrono::milliseconds> microClock_type;
microClock_type tp1 = chrono::time_point_cast<chrono::milliseconds>(chrono::system_clock::now());
long long time1 = tp1.time_since_epoch().count();
//創(chuàng)建線程
thread t1(fun);
thread t2(fun);
t1.join();
t2.join();
cout << "總數(shù):" << g_num << endl;
//獲取當(dāng)前毫秒時間戳
microClock_type tp2 = chrono::time_point_cast<chrono::milliseconds>(chrono::system_clock::now());
long long time2 = tp2.time_since_epoch().count();
cout << "耗時:" << time2 - time1 << "ms" << endl;
getchar();
return 1;
}
執(zhí)行結(jié)果:多次測試輸出均為20000000,耗時在1.3s左右

五:小結(jié)
c++11的原子類atomic相比使用加鎖機(jī)制性能有2~3倍提升,對于共享變量能用原子類型的就不要再用加鎖機(jī)制了。
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,謝謝大家對腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請查看下面相關(guān)鏈接
相關(guān)文章
C語言實現(xiàn)順序表的基本操作指南(注釋很詳細(xì))
線性表是最簡單的數(shù)據(jù)結(jié)構(gòu),而順序表又是最簡單的線性表,其基本思想是用一段地址連續(xù)的儲存單元依次存儲線性表的數(shù)據(jù)元素,下面這篇文章主要給大家介紹了關(guān)于C語言實現(xiàn)順序表的基本操作,需要的朋友可以參考下2021-10-10
解析C++中多層派生時的構(gòu)造函數(shù)及一些特殊形式
這篇文章主要介紹了解析C++中多層派生時的構(gòu)造函數(shù)及一些特殊形式,特殊形式主要針對基類和子對象類型的構(gòu)造函數(shù)內(nèi)容,需要的朋友可以參考下2015-09-09
C語言數(shù)據(jù)結(jié)構(gòu)之循環(huán)鏈表的簡單實例
這篇文章主要介紹了C語言數(shù)據(jù)結(jié)構(gòu)之循環(huán)鏈表的簡單實例的相關(guān)資料,需要的朋友可以參考下2017-06-06

