最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解C++11原子類型與原子操作

 更新時間:2020年08月12日 09:39:08   作者:Dabelv  
這篇文章主要介紹了C++11原子類型與原子操作的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)c++,感興趣的朋友可以了解下

1.認(rèn)識原子操作

原子操作就是在多線程程序中“最小的且不可并行化的”操作,意味著多個線程訪問同一個資源時,有且僅有一個線程能對資源進(jìn)行操作。通常情況下原子操作可以通過互斥的訪問方式來保證,例如Linux下的互斥鎖(mutex),Windows下的臨界區(qū)(Critical Section)等。下面看一個Linux環(huán)境使用POSIX標(biāo)準(zhǔn)的pthread庫實現(xiàn)多線程下的原子操作:

#include <pthread.h>
#include <iostream>
using namespace std;

int64_t total=0;
pthread_mutex_t m=PTHREAD_MUTEX_INITIALIZER;

//線程函數(shù),用于累加
void* threadFunc(void* args)
{
  int64_t endNum=*(int64_t*)args;
  for(int64_t i=1;i<=endNum;++i)
  {
    pthread_mutex_lock(&m);
    total+=i;
    pthread_mutex_unlock(&m);
  }
}

int main()
{
  int64_t endNum=100;
  pthread_t thread1ID=0,thread2ID=0;
  
  //創(chuàng)建線程1
  pthread_create(&thread1ID,NULL,threadFunc,&endNum);
  //創(chuàng)建線程2
  pthread_create(&thread2ID,NULL,threadFunc,&endNum);
  
  //阻塞等待線程1結(jié)束并回收資源
  pthread_join(thread1ID,NULL);
  //阻塞等待線程2結(jié)束并回收資源
  pthread_join(thread2ID,NULL);

  cout<<"total="<<total<<endl;	//10100
}

上面的代碼,兩個線程同時對total進(jìn)行操作,為了保證total+=i 的原子性,采用互斥鎖來保證同一時刻只有同一線程執(zhí)行total+=i操作,所以得出正確結(jié)果total=10100。如果沒有做互斥處理,那么total同一時刻可能會被兩個線程同時操作,即會出現(xiàn)兩個線程同時讀取了寄存器中的total值,分別操作之后又寫入寄存器,這樣就會有一個線程的增加操作無效,會得出一個小于10100隨機(jī)的錯誤值。

2.C++11實現(xiàn)原子操作

在C++11之前,使用第三方API可以實現(xiàn)并行編程,比如pthread多線程庫,但是在使用時需要創(chuàng)建互斥鎖,以及進(jìn)行加鎖、解鎖等操作來保證多線程對臨界資源的原子操作,這無疑增加了開發(fā)的工作量。不過從C++11開始,C++從語言層面開始支持并行編程,內(nèi)容包括了管理線程、保護(hù)共享數(shù)據(jù)、線程間的同步操作、低級原子操作等各種類。新標(biāo)準(zhǔn)極大地提高了程序的可移植性,以前的多線程依賴于具體的平臺,而現(xiàn)在有了統(tǒng)一的接口。

C++11通過引入原子類型幫助開發(fā)者輕松實現(xiàn)原子操作。

#include <atomic>
#include <thread>
#include <iostream>
using namespace std;

atomic_int64_t total = 0;  //atomic_int64_t相當(dāng)于int64_t,但是本身就擁有原子性

//線程函數(shù),用于累加
void threadFunc(int64_t endNum)
{
	for (int64_t i = 1; i <= endNum; ++i)
	{
		total += i;
	}
}

int main()
{
	int64_t endNum = 100;
	thread t1(threadFunc, endNum);
	thread t2(threadFunc, endNum);

	t1.join();
	t2.join();

	cout << "total=" << total << endl; //10100
}

程序正常編譯并運(yùn)行輸出正確結(jié)果total=10100。使用C++11提供的原子類型與多線程標(biāo)準(zhǔn)接口,簡潔地實現(xiàn)了多線程對臨界資源的原子操作。原子類型C++11中通過atomic<T>類模板來定義,比如atomic_int64_t是通過typedef atomic<int64_t> atomic_int64_t實現(xiàn)的,使用時需包含頭文件<atomic>。除了提供atomic_int64_t,還提供了其它的原子類型。常見的原子類型有

原子類型名稱

對應(yīng)內(nèi)置類型

atomic_bool

bool

atomic_char

atomic_char

atomic_char

signed char

atomic_uchar

unsigned char

atomic_short

short

atomic_ushort

unsigned short

atomic_int

int

atomic_uint

unsigned int

atomic_long

long

atomic_ulong

unsigned long

atomic_llong

long long

atomic_ullong

unsigned long long

atomic_ullong

unsigned long long

atomic_char16_t

char16_t

atomic_char32_t

char32_t

atomic_wchar_t

wchar_t

原子操作是平臺相關(guān)的,原子類型能夠?qū)崿F(xiàn)原子操作是因為C++11對原子類型的操作進(jìn)行了抽象,定義了統(tǒng)一的接口,并要求編譯器產(chǎn)生平臺相關(guān)的原子操作的具體實現(xiàn)。C++11標(biāo)準(zhǔn)將原子操作定義為atomic模板類的成員函數(shù),包括讀(load)、寫(store)、交換(exchange)等。對于內(nèi)置類型而言,主要是通過重載一些全局操作符來完成的。比如對上文total+=i的原子加操作,是通過對operator+=重載來實現(xiàn)的。使用g++編譯的話,在x86_64的機(jī)器上,operator+=()函數(shù)會產(chǎn)生一條特殊的以lock為前綴的x86_64指令,用于控制總線及實現(xiàn)x86_64平臺上的原子性加法。

有一個比較特殊的原子類型是atomic_flag,因為atomic_flag與其他原子類型不同,它是無鎖(lock_free)的,即線程對其訪問不需要加鎖,而其他的原子類型不一定是無鎖的。因為atomic<T>并不能保證類型T是無鎖的,另外不同平臺的處理器處理方式不同,也不能保證必定無鎖,所以其他的類型都會有is_lock_free()成員函數(shù)來判斷是否是無鎖的。atomic_flag只支持test_and_set()以及clear()兩個成員函數(shù),test_and_set()函數(shù)檢查 std::atomic_flag 標(biāo)志,如果 std::atomic_flag 之前沒有被設(shè)置過,則設(shè)置 std::atomic_flag 的標(biāo)志;如果之前 std::atomic_flag 已被設(shè)置,則返回 true,否則返回 false。clear()函數(shù)清除 std::atomic_flag 標(biāo)志使得下一次調(diào)用 std::atomic_flag::test_and_set()返回 false??梢杂胊tomic_flag的成員函數(shù)test_and_set()和clear()來實現(xiàn)一個自旋鎖(spin lock):

#include <unistd.h>
#include <atomic>
#include <thread>
#include <iostream>

std::atomic_flag lock = ATOMIC_FLAG_INIT;

void func1()
{
	while (lock.test_and_set(std::memory_order_acquire)) // 在主線程中設(shè)置為true,需要等待t2線程clear
 {
  std::cout << "func1 wait" << std::endl;
 }
 std::cout << "func1 do something" << std::endl;
}

void func2()
{
 std::cout << "func2 start" << std::endl;
 lock.clear();
}

int main()
{
 lock.test_and_set();    // 設(shè)置狀態(tài)
 std::thread t1(func1);
 usleep(1);					 	//睡眠1us
 std::thread t2(func2);

 t1.join();
 t2.join();

 return 0;
}

以上代碼中,定義了一個atomic_flag對象lock,使用初始值A(chǔ)TOMIC_FLAG_INIT進(jìn)行初始化,即處于false的狀態(tài)。線程t1調(diào)用test_and_set()一直返回true(因為在主線程中被設(shè)置過),所以一直在等待,而等待一段時間后當(dāng)線程t2運(yùn)行并調(diào)用了clear(),test_and_set()返回了false退出循環(huán)等待并進(jìn)行相應(yīng)操作。這樣一來,就實現(xiàn)了一個線程等待另一個線程的效果。當(dāng)然,可以封裝成鎖操作的方式,比如:

void Lock(atomic_flag& lock){ while ( lock.test_and_set()); }
void UnLock(atomic_flag& lock){ lock.clear(); }

這樣一來,就可以通過Lock()和UnLock()的方式來互斥地訪問臨界區(qū)。

以上就是詳解C++11原子類型與原子操作的詳細(xì)內(nèi)容,更多關(guān)于C++11原子類型與原子操作的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C語言二叉樹層序遍歷

    C語言二叉樹層序遍歷

    這篇文章主要介紹了C語言二叉樹層序遍歷,文章基于C語言的相關(guān)資料展開詳細(xì)的文章內(nèi)容,具有一定的參考價值,需要的小伙伴可以參考一下,希望對你的學(xué)習(xí)有所幫助
    2022-04-04
  • 詳解C++中遞增運(yùn)算符重載的實現(xiàn)

    詳解C++中遞增運(yùn)算符重載的實現(xiàn)

    本文主要詳解運(yùn)算符重載里的遞增運(yùn)算符重載;遞增和遞減原理是一樣的,這里就只分享遞增的重載;提到遞增遞減,我們都知道又前置和后置兩種方法, 那今天就詳解一下前置遞增和后置遞增的細(xì)節(jié),拿捏遞增運(yùn)算符重載
    2022-06-06
  • C++ 11和C++98相比有哪些新特性

    C++ 11和C++98相比有哪些新特性

    C++11標(biāo)準(zhǔn)提供了許多有用的新特性。這篇文章特別針對使C++11和C++98相比看上去像一門新語言的特性
    2017-03-03
  • C++如何去掉字符串首尾的空格

    C++如何去掉字符串首尾的空格

    這篇文章主要介紹了C++如何去掉字符串首尾的空格問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • C++運(yùn)算符重載圖文詳解

    C++運(yùn)算符重載圖文詳解

    運(yùn)算符重載的方法是定義一個重載運(yùn)算符的函數(shù),在需要執(zhí)行被重載的運(yùn)算符時,系統(tǒng)就自動調(diào)用該函數(shù),以實現(xiàn)相應(yīng)的運(yùn)算。也就是說,運(yùn)算符重載是通過定義函數(shù)實現(xiàn)的
    2021-09-09
  • C/C++?Qt數(shù)據(jù)庫與SqlTableModel組件應(yīng)用教程

    C/C++?Qt數(shù)據(jù)庫與SqlTableModel組件應(yīng)用教程

    SqlTableModel?組件可以將數(shù)據(jù)庫中的特定字段動態(tài)顯示在TableView表格組件中,這篇文章將主要介紹SqlTableModel組件一些常用的操作,需要的朋友可以參考一下
    2021-12-12
  • C++的sstream標(biāo)準(zhǔn)庫詳細(xì)介紹

    C++的sstream標(biāo)準(zhǔn)庫詳細(xì)介紹

    以下是對C++中的的sstream標(biāo)準(zhǔn)庫進(jìn)行了詳細(xì)的介紹,需要的朋友可以過來參考下
    2013-09-09
  • C++實現(xiàn)list增刪查改模擬的示例代碼

    C++實現(xiàn)list增刪查改模擬的示例代碼

    本文主要介紹了C++實現(xiàn)list增刪查改模擬,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-12-12
  • C++中std::optional的使用指南分享

    C++中std::optional的使用指南分享

    C++?17?引入了std::optional,表示一個可能有值的對象,這篇文章主要來和大家聊聊std::optional的使用,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下
    2023-06-06
  • C語言實現(xiàn)拼圖小游戲

    C語言實現(xiàn)拼圖小游戲

    這篇文章主要為大家詳細(xì)介紹了C語言實現(xiàn)拼圖小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-03-03

最新評論

如东县| 瑞金市| 华宁县| 同心县| 上饶县| 昌图县| 鄢陵县| 长葛市| 桂林市| 龙州县| 吉首市| 密云县| 墨竹工卡县| 武威市| 军事| 文化| 塔河县| 岚皋县| 宁阳县| 海伦市| 滦南县| 曲靖市| 芦山县| 贵南县| 泰州市| 上思县| 达孜县| 柳林县| 格尔木市| 闵行区| 灵璧县| 泾川县| 聂荣县| 永胜县| 水富县| 鄂温| 辽阳县| 尼玛县| 措美县| 航空| 新津县|