内存模型和指令重排

本文介绍了Go语言中的内存模型,强调了在并发环境下多Goroutine访问变量的可见性问题。内存模型通过happens-before关系保证了顺序性,避免了指令重排带来的不确定性。Go不提供直接的CPU屏障,而是利用内存屏障指令实现并发原语。文章还详细讨论了Go内存模型中的happens-before保证,包括初始化顺序、Channel操作、Mutex和RWMutex的同步以及WaitGroup和Once的使用。
摘要由CSDN通过智能技术生成

go的内存模型:并发环境中多 goroutine 读相同变量的时候,变量的可见性条件。

  • 什么条件下goroutine 在读取一个变量的值的时候,能够看到其它 goroutine 对这个变量进行的写的结果。

为什么会出现这个问题:

  • 因为会发生指令重排和多级Cache的存在,使得多线程同时访问同一个变量的可见性和顺序需要一个规范。这个规范叫做内存模型。

为什么定义内存模型:

  • 想程序员提供一种保证,在面对同一个数据同时被多个goroutine访问的情况,可以做一些串行化访问的控制,比如使用channel或者sync包和sync/atomic包中的并发原语
  • 允许编译器和硬件对程序做一些优化

指令重排和可见性问题

程序在运行的时候,两个操作的顺序可能不会得到保证。重排以及多核 CPU 并发执行导致程序的运行和代码的书写顺序不一样。但是,如果某些操作能够提供happens-before关系,我们就可以100%保证指令运行的顺序。

在一个goroutine 内部,程序的执行顺序和它们的代码指定的顺序是一样的。对于另一个 goroutine 来说,重排却会产生非常大的影响。因为 Go 只保证 goroutine 内部重排对读写的顺序没有影响。即一个线程内部的执行顺序对另一个线程来说是不确定的。

Go内存模型通过happens-before定义两个事件的顺序,要么先发生要么后发生,否则认为是同时。

tips:

  1. 在 Go 语言中,对变量进行零值的初始化就是一个写操作。
  2. 如果对超过机器 word(64bit、32bit 或者其它)大小的值进行读写
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值