C++11之atomic原子操作

  • atomic介紹

atomic對int、char、bool等數據結構進行了原子性封裝,在多線程環境中,對std::atomic對象的訪問不會造成競爭-冒險。利用std::atomic可實現數據結構的無鎖設計。

所謂的原子操作,取的就是“原子是最小的、不可分割的最小個體”的意義,它表示在多個線程訪問同一個全局資源的時候,能夠確保所有其他的線程都不在同一時間內訪問相同的資源。也就是他確保了在同一時刻只有唯一的線程對這個資源進行訪問。這有點類似互斥對象對共享資源的訪問的保護,但是原子操作更加接近底層,因而效率更高。

在以往的C++標準中並沒有對原子操作進行規定,我們往往是使用彙編語言,或者是藉助第三方的線程庫,例如intel的pthread來實現。在新標準C++11,引入了原子操作的概念,並通過這個新的頭文件提供了多種原子操作數據類型,例如,atomic_bool,atomic_int等等,如果我們在多個線程中對這些類型的共享資源進行操作,編譯器將保證這些操作都是原子性的,也就是說,確保任意時刻只有一個線程對這個資源進行訪問,編譯器將保證,多個線程訪問這個共享資源的正確性。從而避免了鎖的使用,提高了效率。

  • atomic高效體現

加鎖不使用atomic:

#include <iostream>
#include <ctime>
#include <mutex>
#include <vector>
#include <thread>

std::mutex mtx;
size_t count = 0;

void threadFun()
{
	for (int i = 0; i < 10000; i++)
	{
		// 防止多個線程同時訪問同一資源
		std::unique_lock<std::mutex> lock(mtx);
		count++;
	}
}

int main(void)
{
	clock_t start_time = clock();

	// 啓動多個線程
	std::vector<std::thread> threads;
	for (int i = 0; i < 10; i++)
		threads.push_back(std::thread(threadFun));
	for (auto&thad : threads)
		thad.join();

	// 檢測count是否正確 10000*10 = 100000
	std::cout << "count number:" << count << std::endl;

	clock_t end_time = clock();
	std::cout << "耗時:" << end_time - start_time << "ms" << std::endl;

	return 0;
}

運行結果



使用atomic:

#include <iostream>
#include <ctime>
#include <vector>
#include <thread>
#include <atomic>


std::atomic<size_t> count(0);

void threadFun()
{
	for (int i = 0; i < 10000; i++)
		count++;
}

int main(void)
{
	clock_t start_time = clock();

	// 啓動多個線程
	std::vector<std::thread> threads;
	for (int i = 0; i < 10; i++)
		threads.push_back(std::thread(threadFun));
	for (auto&thad : threads)
		thad.join();

	// 檢測count是否正確 10000*10 = 100000
	std::cout << "count number:" << count << std::endl;

	clock_t end_time = clock();
	std::cout << "耗時:" << end_time - start_time << "ms" << std::endl;

	return 0;
}
運行結果



總結

從上面的截圖可以發現,第一張圖用時2439ms,第二張圖用時13ms,使用原子操作能大大的提高程序的運行效率。

  • 參考文檔
博客地址:https://blog.csdn.net/yockie/article/details/8838686
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章