goalng-sync/atomic原子操作
1.go已经提供了锁,为什么还需要atomic原子操作?
1.加锁代价比较高,耗时多,需要上下文切换。加锁解锁在代码层实现,而代码是运行在用户态空间中,对底层进行操作时需要从用户态空间切换到内核空间,再由内核操作底层资源。耗时多
2.原子操作在用户态可以完成,性能比互斥锁高。原子操作在cpu层面支持的,cpu可以直接操作底层资源
3.原子操作需求步骤简单,无需加锁解锁步骤
2.atomic原子操作为什么比mutex快?
1.原子操作快,是因为依赖于cpu指令,而不是依赖外部锁。不会额外的上下文切换
2.原子操作能够保证执行期间是连续且不会被中断(变量不会被其他修改,mutex可能存在被其他修改的情况)
3.CAS
CAS是cpu硬件同步原语,是Compare And Swap的缩写(比较并交换),原子操作中CAS,再sync/atomic包中,全部以ComparAndSwap开头的函数名都是CAS操作
go中CAS操作,是借用CPU提供的原子性指令来实现。CAS操作修改共享变量时,不需要对共享变量加锁,而是通过类似乐观锁的方式进行检查,本质还是不断的占用CPU资源换取加锁带来的开销(如上下文切换时间开销)。
原子操作优势:
可以在不形成临界区和创建互斥量的情况下完成并发安全的值替换操作。这可以大大的减少同步对程序性能的损耗。
原子操作劣势:
在被操作值被频繁的变更的情况下,CAS操作并不那么容易成功。因为需要对ild值进行匹配,只有匹配成功了才进行下一步的修改。
当前atmomic包有以下几种原子操作:
Add,ComparAndSwap,Load,Store,Swap
4.互斥锁与原子操作区别
互斥锁目的:互斥锁是用来保护一段逻辑的,保证并发安全。(比如操作数据库保护)
原子操作目的:原子操作作用于一个变量的更新保护,保证并发安全(比如操作数据库不能原子操作)
mutex底层实现:mutex由操作系统的调度器实现
原子操作底层实现:由底层硬件指令直接提供支持,这些指令在执行过程中不允许中断,因此原子操作可以在无锁的情况下保证并发安全,性能随cpu的数量增多而线性扩展。
5.原子操作方法
5.1 atomic.AddInt32--增减
增减,操作方法的命名方式为AddXXX,保证对操作数进行原子的增减,支持的类型为int32、int64、uint32、uint64、uintptr,使用时以AddXXX就是对应的操作方法。
//加
func demo() {
var count int32 = 0
atomic.AddInt32(&count, 10)
fmt.Println(count) //10
}
//减
func demo() {
var count int32 = 0
atomic.AddInt32(&count, -10)
fmt.Println(count) //-10
}
锁和原子操作对比:
//Mutex锁
func demo1() {
sta := time.Now().Unix()
count := 0
mux := sync.Mutex{}
wg := sync.WaitGroup{}
for i := 0; i < 10000; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for j := 0; j < 10000; j++ {
mux.Lock()
count++
mux.Unlock()
}
}()
}
wg.Wait()
fmt.Println(count) //100000000
fmt.Println(time.Now().Unix() - sta) //10秒
}
//atomic原子操作:快2倍不止
func demo2() {
sta := time.Now().Unix()
wg := sync.WaitGroup{}
var count int32 = 0
for i := 0; i < 10000; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for j := 0; j < 10000; j++ {
atomic.AddInt32(&count, 1)
}
}()
}
wg.Wait()
fmt.Println(count) //100000000
fmt.Println(time.Now().Unix() - sta) //4秒
}
5.2 CAS-atomic.CompareAndSwapInt32--比较并替换
CompareAndSwap:比较并替换,类似乐观锁,先比较下old值与当前值是否一致,一致则把new的值替换
操作方法的命名方式为CompareAndSwapXXX
//true
func demo3() {
var count int32 = 0
boo := atomic.CompareAndSwapInt32(&count, 0, 100)
fmt.Println(count) //100
fmt.Println(boo) //true
}
//false
func demo3() {
var count int32 = 0
boo := atomic.CompareAndSwapInt32(&count, 10, 100)
fmt.Println(count) //0
fmt.Println(boo) //false
}
5.3 atomic.StoreInt32--写操作
func demo3() {
var count int32 = 0
atomic.StoreInt32(&count, 666)
fmt.Println(count) //666
}
5.4 atomic.LoadInt32--读操作
func demo3() {
var count int32 = 0
atomic.StoreInt32(&count, 666)
val := atomic.LoadInt32(&count)
fmt.Println(val) //666
}
5.5 atomic.SwapInt32--直接交换
atomic.SwapInt32:直接交换,并返回交换前的值
func demo3() {
var count int32 = 0
old := atomic.SwapInt32(&count, 100)
fmt.Println(old) //0
fmt.Println(count) //100
}
goalng-sync/atomic原子操作的更多相关文章
- golang sync/atomic
刚刚学习golang原子操作处理的时候发现github上面一个比较不错的golang学习项目 附上链接:https://github.com/polaris1119/The-Golang-Standa ...
- 原子操作--sync/atomic的用法
golang 通过sync/atomic库来支持cpu和操作系统级别的原子操作.但是对要操作类型有如下要求 int32, int64,uint32, uint64,uintptr,unsafe包中的P ...
- atomic 原子操作
原子操作:操作仅由一个独立的CPU指令代表和完成.保证并发环境下原子操作的绝对安全 标准库代码包:sync/atomic atomic是最轻量级的锁,在一些场景下直接使用atomic包还是很有效的 C ...
- 并发之java.util.concurrent.atomic原子操作类包
15.JDK1.8的Java.util.concurrent.atomic包小结 14.Java中Atomic包的原理和分析 13.java.util.concurrent.atomic原子操作类包 ...
- golang语言中sync/atomic包的学习与使用
package main; import ( "sync/atomic" "fmt" "sync" ) //atomic包提供了底层的原子级 ...
- C++11开发中的Atomic原子操作
C++11开发中的Atomic原子操作 Nicol的博客铭 原文 https://taozj.org/2016/09/C-11%E5%BC%80%E5%8F%91%E4%B8%AD%E7%9A%84 ...
- 深入理解Atomic原子操作和volatile非原子性
原子操作可以理解为: 一个数,很多线程去同时修改它,不加sync同步锁,就可以保证修改结果是正确的 Atomic正是采用了CAS算法,所以可以在多线程环境下安全地操作对象. volatile是Java ...
- atomic原子操作
C++中对共享数据的存取在并发条件下可能会引起data race的未定义行为,需要限制并发程序以某种特定的顺序执行,有两种方式:1.使用mutex保护共享数据: 2.原子操作 原子操作:针对原子类型操 ...
- 深入理解java:2.3.1. 并发编程concurrent包 之Atomic原子操作(循环CAS)
java中,可能有一些场景,操作非常简单,但是容易存在并发问题,比如i++, 此时,如果依赖锁机制,可能带来性能损耗等问题, 于是,如何更加简单的实现原子性操作,就成为java中需要面对的一个问题. ...
随机推荐
- unity---寻路导航
寻路导航 1. 简单的寻路 先搭建出类似下面的结构 将你想作为障碍的物体放入一个空物体中 进入空物体点击Static,仅勾选 Navigation Static 即可 依次点击 Window-> ...
- 132_Power BI之建模必备要素&Power Query之数据表字段名称管理
博客:www.jiaopengzi.com 焦棚子的文章目录 请点击下载附件 一.背景 近段时间比较忙,也没有看到很好的DAX素材,很久没有更新文章了,刚好有时间就来凑个热闹. 今天主题是Power ...
- 2020级cpp上机考试题解#B卷
A卷的第七题我只会一个个排除的方法 意思就是暂时没有好办法所以A卷不搞了 1:递归函数求数列 题意: 有一个递归函数int f(int m),计算结果代表了数列的第m项.当m等于1时,函数结果返回1: ...
- 分布式机器学习:逻辑回归的并行化实现(PySpark)
1. 梯度计算式导出 我们在博客<统计学习:逻辑回归与交叉熵损失(Pytorch实现)>中提到,设\(w\)为权值(最后一维为偏置),样本总数为\(N\),\(\{(x_i, y_i)\} ...
- 浅谈BSGS和EXBSGS
我的 BSGS 和各位犇犇的差不多,但是不需要求逆元 Luogu [ TJOI2007 ] 可爱的质数 原题展现 题目描述 给定一个质数 \(p\),以及一个整数 \(b\),一个整数 \(n\),现 ...
- 「ARC138E」Decreasing Subsequence(n logn 做法)
考虑一张 \(n\) 个点的图(\(V=\{0,1,\cdots,n\}\)):点 \(i\) 连向 \(a_i-1\),即 \(\text{index}\) 连向 \(\text{value}\). ...
- 在项目中如何直接使用hystrix?
一.背景 最近由于一些背景原因,需要在项目中需要对接口进行限流.所以就考虑到了直接使用Hystrix.但是呢,又不想直接使用SpringCloud,而是直接引入原生,现在发现挺好用的,所以记录下来,分 ...
- React简单教程-3.1-样式之使用 tailwindcss
前言 本文是作为一个额外内容,主要介绍 tailwindcss 的用法 tailwindcss 是一个功能类优先的 CSS 框架,我在以前的文章里有描述为什么使用功能类优先:为什么我在 css 里使用 ...
- JAVA - ArrayList是否会越界?
JAVA - ArrayList是否会越界? ArrayList并发add()可能出现数组下标越界异常. ArrayList是实现了基于动态数组的数据结构. LinkedList是基于链表的数据结构 ...
- JS:typeof
想要弄明白某一个变量中保存的数据到底是什么数据类型,我们可以使用到typeof操作符. typeof操作符:检测变量的数据类型. 看例子! var a = "abc"; var b ...