Golang 原子操作与互斥锁

先来看一个代码

package mainimport ("fmt""runtime""sync"
)var (counter  int32wg sync.WaitGroup
)func main() {wg.Add(2) // 设置需要等待的 goroutine 的数量为 2go addCounter("Gerald")go addCounter("Seligman")wg.Wait()fmt.Println("Final Counter is: %+v", counter)
}func addCounter(whoAmI string) {defer wg.Done()for count := 0; count < 2;  count++ {value := counter// Gosched使当前go程放弃处理器,以让其它go程运行。它不会挂起当前go程,因此当前go程未来会恢复执行。runtime.Gosched()value++counter = value}
}

Final Counter is: 2

首先这个程序是起了两个 goroutine 。每个 goroutine 都对 counter 进行了两次累加操作,所以理论上 counter 最后应该是 4 而不是 2 。

原因是因为,Gerald 协程获取到 counter 的值后,又让 Seligman 协程去获取 counter 的值。注意此时 counter 的值还没改变,所以他们两个协程都拿到 0 这个值。然后两个协程又将 value++ 后赋值给 counter,等于说做了两次 counter = 1 的操作。第二次循环也是一样的原理。所以最后的值是 2 。

这种情况可以用两中方式避免

  • Atomic 原子操作
  • Mutex 互斥锁

Atomic

for count := 0; count < 2;  count++ {value := counter// Gosched使当前go程放弃处理器,以让其它go程运行。它不会挂起当前go程,因此当前go程未来会恢复执行。runtime.Gosched()value++counter = value}

这段代码其实有点奇怪,为什么给 counter + 1 要写得这么多步。这其实是在模拟 CPU 内部再给你个值+1的时候需要做的操作。首先寄存器会把 counter 的值拿出来保存在寄存器里,然后在寄存器里进行+1操作,最后再把寄存器里的值放到CPU里(原理是这样,若位置错误,请及时提醒,见谅)。

而 Atomic 就是相当于在 CPU 里加锁,让这三步操作在执行的时候,当前协程不可以被调度切换,等这三步完成之后才可以被调度切换。

package mainimport ("fmt""runtime""sync""sync/atomic"
)var (counter  int32wg sync.WaitGroup
)func main() {wg.Add(2) // 设置需要等待的 goroutine 的数量为 2go addCounter("Gerald")go addCounter("Seligman")wg.Wait()fmt.Println("Final Counter is: ", counter)
}func addCounter(whoAmI string) {defer wg.Done()for count := 0; count < 2;  count++ {//value := counter// Gosched使当前go程放弃处理器,以让其它go程运行。它不会挂起当前go程,因此当前go程未来会恢复执行。//runtime.Gosched()////value++////counter = valueatomic.AddInt32(&counter, 1)runtime.Gosched()}
}

Final Counter is: 4

这次 counter 就变成 4 了,符合预期。

Mutex

这个应该很熟悉了,互斥锁,就是在对元素操作之前进行加锁,操作完了解锁。就可以保证数据一致了。

package mainimport ("fmt""sync"
)var (counter  int32wg sync.WaitGroupmutex sync.Mutex
)func main() {wg.Add(2) // 设置需要等待的 goroutine 的数量为 2go addCounter("Gerald")go addCounter("Seligman")wg.Wait()fmt.Println("Final Counter is: ", counter)
}func addCounter(whoAmI string) {defer wg.Done()for count := 0; count < 2;  count++ {//value := counter// Gosched使当前go程放弃处理器,以让其它go程运行。它不会挂起当前go程,因此当前go程未来会恢复执行。//runtime.Gosched()////value++////counter = value//atomic.AddInt32(&counter, 1)//runtime.Gosched()mutex.Lock()counter++mutex.Unlock()}
}

Final Counter is: 4

叮~

Golang 原子操作与互斥锁相关推荐

  1. Go语言的原子操作和互斥锁的区别

    这个系列的文章里介绍了很多并发编程里经常用到的技术,除了Context.计时器.互斥锁还有通道外还有一种技术--原子操作在一些同步算法中会被用到.今天的文章里我们会简单了解一下Go语言里对原子操作的支 ...

  2. 原子操作和互斥锁的区别

    这个系列的文章里介绍了很多并发编程里经常用到的技术,除了Context.计时器.互斥锁还有通道外还有一种技术--原子操作在一些同步算法中会被用到.今天的文章里我们会简单了解一下Go语言里对原子操作的支 ...

  3. 原子操作、互斥锁、读写锁

    原子操作 package mainimport ("fmt""sync""sync/atomic" //原子操作,比读写锁和互斥锁都要快,原 ...

  4. golang RWMutex读写互斥锁源码分析

    针对Golang 1.9的sync.RWMutex进行分析,与Golang 1.10基本一样除了将panic改为了throw之外其他的都一样. RWMutex是读写互斥锁.锁可以由任意数量的读取器或单 ...

  5. golang sync.Mutex 互斥锁 使用实例

    实例: var mutex sync.Mutex //互斥锁 func printer(str string){mutex.Lock() //加锁defer mutex.Unlock() //解锁fo ...

  6. golang中的互斥锁

    简介 每个资源都对应一个可称为"互斥锁"的标记,这个标记用来保证在任意时刻,只有一个协程(线程)访问该资源.其他的协程只能等待 由标准库sync中的Mutex结构体类型表示. sy ...

  7. Golang——死锁、互斥锁、读写锁的实现

    死锁: 什么是锁呢?就是某个协程(线程)在访问某个资源时先锁住,防止其它协程的访问,等访问完毕解锁后其他协程再来加锁进行访问.这和我们生活中加锁使用公共资源相似,例如:公共卫生间. 死锁是指两个或两个 ...

  8. 原子操作和互斥量的区别

    原子操作和互斥量的区别 原子操作和互斥锁都是并发编程中常见的技术. 原子操作 原子操作就是操作过程中不能被中断的过程,在针对某个值得原子操作,在被进行的过程中CPU绝对不会再进行其他的针对该值的操作. ...

  9. Linux并发与竞争介绍(原子操作、自旋锁、信号量、互斥体)

    目录 并发与竞争 并发与竞争简介 保护内容是什么 原子操作 原子操作简介 原子整形操作API函数(atomic_t 结构体) 原子位操作API 函数 自旋锁 自旋锁简介 自旋锁API函数 线程与线程 ...

  10. Linux C/C++ 并发下的技术方案(互斥锁、自旋锁、原子操作)

    前言 线程:是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务.在Uni ...

最新文章

  1. Android选项卡置底的方法
  2. 摘要: Nginx 网络多并发请求的TCP网络参数做简单说明。
  3. Swift 基本基本运算符
  4. 安装go语言开发环境
  5. 情商(实践版本,丹尼尔.戈尔曼)---阅读记录
  6. (转)js实现继承的5种方式
  7. ITK:标记连接组件的轮廓
  8. java决策树_【Java】决策树介绍和使用
  9. mac 上传ftp服务器文件夹权限,mac 访问 ftp服务器文件夹权限
  10. 产品经理必看:终于有人把数据指标讲明白了
  11. 19.删除链表的倒数第N个节点
  12. 怎么禁用域控下的计算机配置,怎样从Windows域环境下禁用USB口设备
  13. 一个维护版本日志整洁的Git提交规范
  14. 计算机成原理第2版,清华大学出版社-图书详情-《计算机组成原理(第2版)》...
  15. Visual Studio2017 数据库架构比较
  16. SpringMVC中请求的转发和重定向
  17. c语言swustoj括号匹配问题,swust-oj 西南科技大学oj练习题解 150+道 - 下载 - 搜珍网...
  18. 音视频开发系列--H264编解码总结
  19. 我工作这十年-中国在崛起
  20. 人体解析任务 和 Look into Person数据集 (附源码分享)

热门文章

  1. 在组策略中 计算机策略仅对,在组策略中,计算机策略仅对()生效。 - 问答库...
  2. OpenCASCADE:OCCT应用框架OCAF之XML支持
  3. CDH大数据平台搭建之HADOOP分布式集群搭建
  4. 大数据人工智能技术全攻略(一)
  5. 配置HRFormer:High-Resolution Transformer for Dense Prediction条件
  6. 迈普路由器访问控制列表配置命令_迈普路由器配置手册
  7. 3、MybatisPlus
  8. 蓝懿iOS 技术内容交流和学习心得 11.11
  9. 通讯录管理系统(C语言版)
  10. 在鹅厂工作1到11年的程序媛