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

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

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

1.認識原子操作

原子操作就是在多線程程序中“最小的且不可并行化的”操作,意味著多個線程訪問同一個資源時,有且僅有一個線程能對資源進行操作。通常情況下原子操作可以通過互斥的訪問方式來保證,例如Linux下的互斥鎖(mutex),Windows下的臨界區(qū)(Critical Section)等。下面看一個Linux環(huán)境使用POSIX標準的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結束并回收資源
  pthread_join(thread1ID,NULL);
  //阻塞等待線程2結束并回收資源
  pthread_join(thread2ID,NULL);

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

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

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

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

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

原子類型名稱

對應內(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

原子操作是平臺相關的,原子類型能夠?qū)崿F(xiàn)原子操作是因為C++11對原子類型的操作進行了抽象,定義了統(tǒng)一的接口,并要求編譯器產(chǎn)生平臺相關的原子操作的具體實現(xiàn)。C++11標準將原子操作定義為atomic模板類的成員函數(shù),包括讀(load)、寫(store)、交換(exchange)等。對于內(nèi)置類型而言,主要是通過重載一些全局操作符來完成的。比如對上文total+=i的原子加操作,是通過對operator+=重載來實現(xiàn)的。使用g++編譯的話,在x86_64的機器上,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 標志,如果 std::atomic_flag 之前沒有被設置過,則設置 std::atomic_flag 的標志;如果之前 std::atomic_flag 已被設置,則返回 true,否則返回 false。clear()函數(shù)清除 std::atomic_flag 標志使得下一次調(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)) // 在主線程中設置為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();    // 設置狀態(tài)
 std::thread t1(func1);
 usleep(1);					 	//睡眠1us
 std::thread t2(func2);

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

 return 0;
}

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

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

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

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

相關文章

  • C語言二叉樹層序遍歷

    C語言二叉樹層序遍歷

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

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

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

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

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

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

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

    C++運算符重載圖文詳解

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

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

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

    C++的sstream標準庫詳細介紹

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

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

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

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

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

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

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

最新評論

吉隆县| 舟山市| 丰县| 高邑县| 天等县| 长治县| 囊谦县| 温州市| 桑植县| 息烽县| 洛隆县| 乌鲁木齐市| 双桥区| 青川县| 枣阳市| 张家界市| 合阳县| 岳池县| 垦利县| 公主岭市| 大田县| 儋州市| 同仁县| 沙洋县| 阿巴嘎旗| 波密县| 广安市| 拜城县| 蓬溪县| 焉耆| 黄冈市| 安西县| 凤台县| 安乡县| 廉江市| 长沙市| 繁昌县| 罗城| 临汾市| 阿克苏市| 南汇区|