亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

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

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

原子操作就是在多線程程序中“最小的且不可并行化的”操作,意味著多個(gè)線程訪問(wèn)同一個(gè)資源時(shí),有且僅有一個(gè)線程能對(duì)資源進(jìn)行操作。通常情況下原子操作可以通過(guò)互斥的訪問(wèn)方式來(lái)保證,例如Linux下的互斥鎖(mutex),Windows下的臨界區(qū)(Critical Section)等。下面看一個(gè)Linux環(huán)境使用POSIX標(biāo)準(zhǔn)的pthread庫(kù)實(shí)現(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
}

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

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

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

C++11通過(guò)引入原子類型幫助開發(fā)者輕松實(shí)現(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)接口,簡(jiǎn)潔地實(shí)現(xiàn)了多線程對(duì)臨界資源的原子操作。原子類型C++11中通過(guò)atomic<T>類模板來(lái)定義,比如atomic_int64_t是通過(guò)typedef atomic<int64_t> atomic_int64_t實(shí)現(xiàn)的,使用時(shí)需包含頭文件<atomic>。除了提供atomic_int64_t,還提供了其它的原子類型。常見的原子類型有

原子類型名稱

對(duì)應(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

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

有一個(gè)比較特殊的原子類型是atomic_flag,因?yàn)閍tomic_flag與其他原子類型不同,它是無(wú)鎖(lock_free)的,即線程對(duì)其訪問(wèn)不需要加鎖,而其他的原子類型不一定是無(wú)鎖的。因?yàn)閍tomic<T>并不能保證類型T是無(wú)鎖的,另外不同平臺(tái)的處理器處理方式不同,也不能保證必定無(wú)鎖,所以其他的類型都會(huì)有is_lock_free()成員函數(shù)來(lái)判斷是否是無(wú)鎖的。atomic_flag只支持test_and_set()以及clear()兩個(gè)成員函數(shù),test_and_set()函數(shù)檢查 std::atomic_flag 標(biāo)志,如果 std::atomic_flag 之前沒有被設(shè)置過(guò),則設(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()來(lái)實(shí)現(xiàn)一個(gè)自旋鎖(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;
}

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

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

這樣一來(lái),就可以通過(guò)Lock()和UnLock()的方式來(lái)互斥地訪問(wèn)臨界區(qū)。

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

相關(guān)文章

  • C++利用類實(shí)現(xiàn)矩陣的數(shù)乘,乘法以及點(diǎn)乘

    C++利用類實(shí)現(xiàn)矩陣的數(shù)乘,乘法以及點(diǎn)乘

    這篇文章主要為大家詳細(xì)介紹了C++如何利用類實(shí)現(xiàn)矩陣的數(shù)乘,乘法以及點(diǎn)乘,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)C++有一定幫助,需要的可以參考一下
    2022-11-11
  • C/C++ 函數(shù)原理傳參示例詳解

    C/C++ 函數(shù)原理傳參示例詳解

    這篇文章主要為大家介紹了C/C++ 函數(shù)原理傳參示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • MFC命名規(guī)則匯總

    MFC命名規(guī)則匯總

    這篇文章主要介紹了MFC命名規(guī)則,對(duì)于初學(xué)者而言需要牢固掌握這類規(guī)則,需要的朋友可以參考下
    2014-07-07
  • C語(yǔ)言中回調(diào)函數(shù)和qsort函數(shù)的用法詳解

    C語(yǔ)言中回調(diào)函數(shù)和qsort函數(shù)的用法詳解

    這篇文章主要為大家詳細(xì)介紹一下C語(yǔ)言中回調(diào)函數(shù)和qsort函數(shù)的用法教程,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)C語(yǔ)言有一定幫助,需要的可以參考一下
    2022-07-07
  • C語(yǔ)言進(jìn)階:指針的進(jìn)階(1)

    C語(yǔ)言進(jìn)階:指針的進(jìn)階(1)

    這篇文章主要介紹了C語(yǔ)言指針詳解及用法示例,介紹了其相關(guān)概念,然后分享了幾種用法,具有一定參考價(jià)值。需要的朋友可以了解下
    2021-09-09
  • 使用C語(yǔ)言繪制柱形圖的示例代碼

    使用C語(yǔ)言繪制柱形圖的示例代碼

    常用的統(tǒng)計(jì)圖有條形圖、柱形圖、折線圖、曲線圖、餅圖、環(huán)形圖、扇形圖,這篇文章主要為大家介紹了C語(yǔ)言中繪制條形圖和柱形圖的方法,需要的可以參考下
    2024-02-02
  • 如何使用VC庫(kù)函數(shù)中的快速排序函數(shù)

    如何使用VC庫(kù)函數(shù)中的快速排序函數(shù)

    下面呢,小編就為大家介紹一下VC中庫(kù)函數(shù)qsort()的用法。需要的朋友可以過(guò)來(lái)參考下
    2013-09-09
  • C++?OpenCV紅綠燈檢測(cè)Demo實(shí)現(xiàn)詳解

    C++?OpenCV紅綠燈檢測(cè)Demo實(shí)現(xiàn)詳解

    OpenCV(Open Source Computer Vision Library)是開源的計(jì)算機(jī)視覺和機(jī)器學(xué)習(xí)庫(kù),提供了C++、 C、 Python、 Java接口,并支持Windows、 Linux、 Android、 Mac OS平臺(tái),下面這篇文章主要給大家介紹了關(guān)于C++?OpenCV紅綠燈檢測(cè)Demo實(shí)現(xiàn)的相關(guān)資料,需要的朋友可以參考下
    2022-11-11
  • Qt sender()函數(shù)的具體使用

    Qt sender()函數(shù)的具體使用

    在處理信號(hào)時(shí),Qt提供了一個(gè)特殊的函數(shù)sender(),可以返回發(fā)送信號(hào)的對(duì)象指針,以實(shí)現(xiàn)更靈活的代碼邏輯,本文就來(lái)介紹一下Qt sender()函數(shù)的具體使用,感興趣的可以了解一下
    2024-01-01
  • C++ Boost命令行解析庫(kù)的應(yīng)用詳解

    C++ Boost命令行解析庫(kù)的應(yīng)用詳解

    命令行解析庫(kù)是一種用于簡(jiǎn)化處理命令行參數(shù)的工具,它可以幫助開發(fā)者更方便地解析命令行參數(shù)并提供適當(dāng)?shù)膸椭畔?本文主要介紹了不同的命令行解析庫(kù)和它們?cè)贑++項(xiàng)目中的應(yīng)用,希望對(duì)大家有所幫助
    2023-11-11

最新評(píng)論