C++11并发编程(四):原子操作

1、原子操作介绍

(1)所谓的原子操作,取的就是“原子是最小的、不可分割的最小个体”的意义,它表示在多个线程访问同一个全局资源的时候,能够确保所有其他的线程都不在同一时间内访问相同的资源。也就是他确保了在同一时刻只有唯一的线程对这个资源进行访问。这有点类似互斥对象对共享资源的访问的保护,但是原子操作更加接近底层,因而效率更高。

(2)在以往的C++标准中并没有对原子操作进行规定,我们往往是使用汇编语言,或者是借助第三方的线程库,例如intel的pthread来实现。在新标准C++11,引入了原子操作的概念,并通过这个新的头文件提供了多种原子操作数据类型,例如,atomic_bool,atomic_int等等,如果我们在多个线程中对这些类型的共享资源进行操作,编译器将保证这些操作都是原子性的,也就是说,确保任意时刻只有一个线程对这个资源进行访问,编译器将保证,多个线程访问这个共享资源的正确性。从而避免了锁的使用,提高了效率。

(3)C++11中引入了原子操作atomic。atomic对int、char、bool等数据结构进行了原子性封装,在多线程环境中,对std::atomic对象的访问不会造成竞争-冒险。

利用std::atomic可实现数据结构的无锁设计。

为了方便使用,c++11为模版函数提供了别名。

atomic<bool>   别名:atomic_bool  

atomic<int>  别名:atomic_int

atomic<char> 别名:atomic_char 

atomic<long> 别名:atomic_long 

2、加锁方式实现数据写入原子操作(效率低)

#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 << "time:" << end_time - start_time << "ms" << std::endl;
 
	return 0;
}

结果:

3、采用C++11提供原子操作

只需要把count原来的int型,改为std::atomic<size_t>型就可以了,非常方便,也不需要用到锁。

#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 << "time:" << end_time - start_time << "ms" << std::endl;
 
	return 0;
}

结果:

4、结论

对比,使用C++11原子操作,运行时间缩短40%,如果跑较复杂任务,可能会更明显。

 

参考链接:

https://blog.csdn.net/qq_34199383/article/details/79990986

 


若对你有帮助,欢迎点赞、收藏、评论,你的支持就是我的最大动力!!!

同时,阿超为大家准备了丰富的学习资料,欢迎关注公众号“超哥学编程”,即可领取。

本文涉及工程代码,公众号回复:04atomic,即可下载

在这里插入图片描述

 


版权声明:本文为u011832525原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。