C++11中的原子操作(atomic operation)和自旋锁
C++11中的原子操作(atomic operation)
- 1. 原子操作
- 2. 自旋锁
- 3. 原子操作和使用互斥锁和自旋锁的速度对比
1. 原子操作
所谓的原子操作,取的就是“原子是最小的、不可分割的最小个体”的意义,它表示在多个线程访问同一个全局资源的时候,能够确保所有其他的线程都不在同一时间内访问相同的资源。
我们在原子操作之前在多线程同步中防止发生数据竞争的操作是加互斥锁,但互斥锁是操作系统这一层级的,最终映射到CPU上也是一堆指令,是指令就必然会带来额外的开销;既然CPU指令是多线程不可再分的最小单元,那我们如果有办法将代码语句和指令对应起来,不就不需要引入互斥锁从而提高性能了吗? 而这个对应关系就是所谓的原子操作;
在新标准C++11,引入了原子操作的概念,并通过这个新的头文件提供了多种原子操作数据类型,例如,atomic_bool
,atomic_int
等等,如果我们在多个线程中对这些类型的共享资源进行操作,编译器将保证这些操作都是原子性的,也就是说,确保任意时刻只有一个线程对这个资源进行访问,编译器将保证,多个线程访问这个共享资源的正确性。从而避免了锁的使用,提高了效率。
2. 自旋锁
自旋锁是一种基础的同步原语,用于保障对共享数据的互斥访问。与互斥锁的相比,在获取锁失败的时候不会使得线程阻塞而是一直自旋尝试获取锁。当线程等待自旋锁的时候,CPU不能做其他事情,而是一直处于轮询忙等的状态。
自旋锁主要适用于被持有时间短,线程不希望在重新调度上花过多时间的情况。实际上许多其他类型的锁在底层使用了自旋锁实现,例如多数互斥锁在试图获取锁的时候会先自旋一小段时间,然后才会休眠。如果在持锁时间很长的场景下使用自旋锁,则会导致CPU在这个线程的时间片用尽之前一直消耗在无意义的忙等上,造成计算资源的浪费。
自旋锁相关API:
int pthread_spin_init(pthread_spinlock_t *, int); //初始化自旋锁
int pthread_spin_lock(pthread_spinlock_t *); //获得一个自旋锁
int pthread_spin_trylock(pthread_spinlock_t *); //尝试获取一个自旋锁
int pthread_spin_unlock(pthread_spinlock_t *);//释放(解锁)一个自旋锁
int pthread_spin_destroy(pthread_spinlock_t *); //销毁一个自旋锁
使用自旋锁注意:
由于自旋时不释放CPU,因而持有自旋锁的线程应该尽快释放自旋锁,否则等待该自旋锁的线程会一直在哪里自旋,这就会浪费CPU时间。
持有自旋锁的线程在sleep之前应该释放自旋锁以便其他线程可以获得该自旋锁
3. 原子操作和使用互斥锁和自旋锁的速度对比
单线程无锁速度最快,但应用场合受限;
多线程无锁速度第二快,但结果不对,未保护临界代码段;
多线程原子锁第三快,且结果正确;
多线程互斥量较慢,慢与原子锁近10倍,结果正确;
多线程自旋锁最慢,慢与原子锁30倍,结果正确。
结论:原子锁速度最快,互斥量和自旋锁都用保护多线程共享资源。
自旋锁是一种非阻塞锁,也就是说,如果某线程需要获取自旋锁,但该锁已经被其他线程占用时,该线程不会被挂起,而是在不断的消耗CPU的时间,不停的试图获取自旋锁。
互斥量是阻塞锁,当某线程无法获取互斥量时,该线程会被直接挂起,该线程不再消耗CPU时间,当其他线程释放互斥量后,操作系统会激活那个被挂起的线程,让其投入运行。
C++11中的原子操作(atomic operation)和自旋锁相关推荐
- 什么是Java中的原子操作( atomic operations)
1.啥是java的原子性 原子性:即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行. 一个很经典的例子就是银行账户转账问题: 比如从账户A向账户B转1000元,那么 ...
- C++11中头文件atomic的使用
原子库为细粒度的原子操作提供组件,允许无锁并发编程.涉及同一对象的每个原子操作,相对于任何其他原子操作是不可分的.原子对象不具有数据竞争(data race).原子类型对象的主要特点就是从不同线程访问 ...
- C++11中std::future的使用
C++11中的std::future是一个模板类.std::future提供了一种用于访问异步操作结果的机制.std::future所引用的共享状态不能与任何其它异步返回的对象共享(与std::sha ...
- 利用C++11原子量atomic实现自旋锁详解
一.自旋锁 自旋锁是一种基础的同步原语,用于保障对共享数据的互斥访问.与互斥锁的相比,在获取锁失败的时候不会使得线程阻塞而是一直自旋尝试获取锁.当线程等待自旋锁的时候,CPU不能做其他事情,而是一直处 ...
- Linux内核中的同步原语:自旋锁,信号量,互斥锁,读写信号量,顺序锁
Linux内核中的同步原语 自旋锁,信号量,互斥锁,读写信号量,顺序锁 rtoax 2021年3月 在英文原文基础上,针对中文译文增加5.10.13内核源码相关内容. 1. Linux 内核中的同步原 ...
- 随机数在java 自旋锁的运用_Java 中自旋锁的实现
Java中初始是使用mutex互斥锁,因为互斥锁是会线程等待挂起,而对获取锁后的操作时间比较短暂的应用场景来说,这样的锁会让竞争锁的线程不停的park,unpark 的操作,这样的系统的调用性能是非常 ...
- Multi-thread--C++11中atomic的使用
原子库为细粒度的原子操作提供组件,允许无锁并发编程.涉及同一对象的每个原子操作,相对于任何其他原子操作是不可分的.原子对象不具有数据竞争(data race).原子类型对象的主要特点就是从不同线程访问 ...
- 探究Java如何实现原子操作(atomic operation)
1. 让我们首先了解下java 中 Volatile 关键字 Volatile可实现java内存模型当中的可见性, java内存模型的可见性: 可见性,是指线程之间的可见性,一个线程修改的状态对另一个 ...
- 原子(atom)本意是“不能被进一步分割的最小粒子”,而原子操作(atomic operation)
1. 引言 原子(atom)本意是"不能被进一步分割的最小粒子",而原子操作(atomic operation)意为"不可被中断的一个或一系列操作" .在多处理 ...
- C++11并发编程:原子操作atomic
一:概述 项目中经常用遇到多线程操作共享数据问题,常用的处理方式是对共享数据进行加锁,如果多线程操作共享变量也同样采用这种方式. 为什么要对共享变量加锁或使用原子操作?如两个线程操作同一变量过程中,一 ...
最新文章
- linux操作系统的特点有哪些,LINUX操作系统有哪些概念和特点?
- Android 数据库之Cursor
- 向vSphere迁移虚拟机,Converter需要升级至4.0.1
- python假设产品列表如下请首先打印出商品列表_Python列表练习题
- VC6自定义注释代码快捷键
- lua_path环境变量设置linux,ubuntu16.04安装lua环境
- java中render用法_如何在React中不在render函数中使用setState
- 小米宣布造车后,雷军与四位造车界大佬合影照曝光
- hibernate缓存详解
- 利用pgAgent创建定时任务
- Youki的Ubuntu系统安装显卡驱动安装笔记~
- 电脑怎么开护眼模式_心累!整天对着手机电脑,到底该怎么护眼啊啊啊
- .Net remoting, Webservice,WCF,Socket区别
- windows winrar 指令_WINRAR 命令行语法
- 日本专利分类方法 FI 和 F-Term 分类号 检索
- 问题处理——无法导航到插入符号下的符号
- openwrt路由器(红米AC2100)折腾全程——多拨、ipv6负载均衡、ipv6 nat6、ddns、端口转发
- 用STEP7-MicroWIN SMART能搜索到CPU 也能控制PLC指示灯闪烁,但是下载程序仍提示当前IP地址失败请检查IP地址、网络连接
- 寻找不能拼读的汉语拼音
- 客户 服务器协议简写,客户端和服务器端的简写