刚刚学习golang原子操作处理的时候发现github上面一个比较不错的golang学习项目

附上链接:https://github.com/polaris1119/The-Golang-Standard-Library-by-Example

下列文章出处源自:https://github.com/polaris1119/The-Golang-Standard-Library-by-Example/blob/master/chapter16/16.02.md

sync/atomic - 原子操作

对于并发操作而言,原子操作是个非常现实的问题。典型的就是i++的问题。 当两个CPU同时对内存中的i进行读取,然后把加一之后的值放入内存中,可能两次i++的结果,这个i只增加了一次。 如何保证多CPU对同一块内存的操作是原子的。 golang中sync/atomic就是做这个使用的。

具体的原子操作在不同的操作系统中实现是不同的。比如在Intel的CPU架构机器上,主要是使用总线锁的方式实现的。 大致的意思就是当一个CPU需要操作一个内存块的时候,向总线发送一个LOCK信号,所有CPU收到这个信号后就不对这个内存块进行操作了。 等待操作的CPU执行完操作后,发送UNLOCK信号,才结束。 在AMD的CPU架构机器上就是使用MESI一致性协议的方式来保证原子操作。 所以我们在看atomic源码的时候,我们看到它针对不同的操作系统有不同汇编语言文件。

如果我们善用原子操作,它会比锁更为高效。

CAS

原子操作中最经典的CAS(compare-and-swap)在atomic包中是Compare开头的函数。

  • func CompareAndSwapInt32(addr *int32, old, new int32) (swapped bool)
  • func CompareAndSwapInt64(addr *int64, old, new int64) (swapped bool)
  • func CompareAndSwapPointer(addr *unsafe.Pointer, old, new unsafe.Pointer) (swapped bool)
  • func CompareAndSwapUint32(addr *uint32, old, new uint32) (swapped bool)
  • func CompareAndSwapUint64(addr *uint64, old, new uint64) (swapped bool)
  • func CompareAndSwapUintptr(addr *uintptr, old, new uintptr) (swapped bool)

CAS的意思是判断内存中的某个值是否等于old值,如果是的话,则赋new值给这块内存。CAS是一个方法,并不局限在CPU原子操作中。 CAS比互斥锁乐观,但是也就代表CAS是有赋值不成功的时候,调用CAS的那一方就需要处理赋值不成功的后续行为了。

这一系列的函数需要比较后再进行交换,也有不需要进行比较就进行交换的原子操作。

  • func SwapInt32(addr *int32, new int32) (old int32)
  • func SwapInt64(addr *int64, new int64) (old int64)
  • func SwapPointer(addr *unsafe.Pointer, new unsafe.Pointer) (old unsafe.Pointer)
  • func SwapUint32(addr *uint32, new uint32) (old uint32)
  • func SwapUint64(addr *uint64, new uint64) (old uint64)
  • func SwapUintptr(addr *uintptr, new uintptr) (old uintptr)

增加或减少

对一个数值进行增加或者减少的行为也需要保证是原子的,它对应于atomic包的函数就是

  • func AddInt32(addr *int32, delta int32) (new int32)
  • func AddInt64(addr *int64, delta int64) (new int64)
  • func AddUint32(addr *uint32, delta uint32) (new uint32)
  • func AddUint64(addr *uint64, delta uint64) (new uint64)
  • func AddUintptr(addr *uintptr, delta uintptr) (new uintptr)

读取或写入

当我们要读取一个变量的时候,很有可能这个变量正在被写入,这个时候,我们就很有可能读取到写到一半的数据。 所以读取操作是需要一个原子行为的。在atomic包中就是Load开头的函数群。

  • func LoadInt32(addr *int32) (val int32)
  • func LoadInt64(addr *int64) (val int64)
  • func LoadPointer(addr *unsafe.Pointer) (val unsafe.Pointer)
  • func LoadUint32(addr *uint32) (val uint32)
  • func LoadUint64(addr *uint64) (val uint64)
  • func LoadUintptr(addr *uintptr) (val uintptr)

好了,读取我们是完成了原子性,那写入呢?也是同样的,如果有多个CPU往内存中一个数据块写入数据的时候,可能导致这个写入的数据不完整。 在atomic包对应的是Store开头的函数群。

  • func StoreInt32(addr *int32, val int32)
  • func StoreInt64(addr *int64, val int64)
  • func StorePointer(addr *unsafe.Pointer, val unsafe.Pointer)
  • func StoreUint32(addr *uint32, val uint32)
  • func StoreUint64(addr *uint64, val uint64)
  • func StoreUintptr(addr *uintptr, val uintptr)

golang sync/atomic的更多相关文章

  1. golang语言中sync/atomic包的学习与使用

    package main; import ( "sync/atomic" "fmt" "sync" ) //atomic包提供了底层的原子级 ...

  2. golang sync包

    sync 在golang 文档上,golang不希望通过共享内存来进行进程间的协同操作,而是通过channel的方式来进行,当然,golang也提供了共享内存,锁等机制进行协同操作的包: 互斥锁: M ...

  3. 原子操作--sync/atomic的用法

    golang 通过sync/atomic库来支持cpu和操作系统级别的原子操作.但是对要操作类型有如下要求 int32, int64,uint32, uint64,uintptr,unsafe包中的P ...

  4. Golang Sync.WaitGroup 使用及原理

    Golang Sync.WaitGroup 使用及原理 使用 func main() { var wg sync.WaitGroup for i := 0; i < 10; i++ { wg.A ...

  5. Golang:sync.Map

    由于map在gorountine 上不是安全的,所以在大量并发读写的时候,会出现错误. 在1.9版的时候golang推出了sync.Map. sync.Map 通过阅读源码我们发现sync.Map是通 ...

  6. golang sync.noCopy 类型 —— 初探 copylocks 与 empty struct

    问题引入 学习golang(v1.16)的 WaitGroup 代码时,看到了一处奇怪的用法,见下方类型定义: type WaitGroup struct { noCopy noCopy ... } ...

  7. golang sync.Cond条件变量的使用

    cond.Wait()的操作实际上是对与cond绑定的锁先进行解锁,在等待通知:接收到通知后,会尝试加锁,加锁成功则唤醒否则继续等待通知: cond.Waite()前必须对关连锁加锁,否则panic ...

  8. Golang sync

    Go1.9.2 sync库里包含下面几类:Mutex/RWMutex/Cond/WaitGroup/Once/Map/Pool 1.Mutex:互斥锁,等同于linux下的pthread_mutex_ ...

  9. golang sync.Pool包的使用和一些注意地方

    package main; import ( "sync" "fmt" "net" "runtime" ) //sync ...

随机推荐

  1. javaScript(6)---流程控制语句

    学习要点: 1.语句的定义 2.if 语句 3.switch语句 4.do...while语句 5.while语句 6.for语句 7.for...in语句 8.break和continue语句 9. ...

  2. layerX参数构建

    var defaults = { name: 'layerX', url: [ { name: 'sub', url: '', focus: true } ], parent: { name: '', ...

  3. mongodb常用语句

    一.查询 find方法 db.collection_name.find(); 查询所有的结果: select * from users; db.users.find(); 指定返回那些列(键): se ...

  4. STOMP协议规范

    原文: STOMP Protocol Specification, Version 1.2 摘要 STOMP是一个简单的可互操作的协议, 被用于通过中间服务器在客户端之间进行异步消息传递.它定义了一种 ...

  5. XYC2016上半年工作笔记整理

    只要团队在,做那个方向都可能 这个产品的用户群人均价值高 第一次产品介绍会议就介绍了产品的初期全部目标功能 传统互联网人的产品思路比较偏媒体内容服务特性. 产品转化率高说明了其发展势头 任何一个形式变 ...

  6. Fiddler抓包使用教程-Android应用抓包

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/74439165 本文出自[赵彦军的博客] Fiddler 也可以支持对手机应用进行 ...

  7. Nginx 怎么给一台服务器,配置两个域名?详细的解说+截图教程

    一.        环境.条件准备 一台云服务器(我的是腾讯的centos7) 至少两个域名.(我的是simuhunluo.xyz和simuhunluo.top.这两个域名之间没有任何关系,我是在阿里 ...

  8. Ubuntu 16.04开启SSH服务

    安装: sudo apt-get install openssh-server 启动: sudo service ssh start 查询服务启动状态: sudo ps -e | grep ssh 或 ...

  9. Java Elasticsearch新手入门教程

    概要: 1.使用Eclipse搭建Elasticsearch详情参考下面链接 2.Java Elasticsearch 配置 3.ElasticSearch Java Api(一) -添加数据创建索引 ...

  10. 14.Ubuntu基本命令

    vi编辑器 {  :上一段diamante } :下一段代码 dw: 删除一个单词 权限 前面的分三组 第一: 文件拥有者的权限 第二:同组者拥有的权限 第三:其他人拥有的权限 前面“-”表示是文件 ...