前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Go 语言 chanel 内存模型

Go 语言 chanel 内存模型

原创
作者头像
王小明_HIT
修改2021-09-13 15:05:03
3600
修改2021-09-13 15:05:03
举报
文章被收录于专栏:程序员奇点程序员奇点

内存模型

Go 内存模型描述的是 “在一个 groutine 中对变量进行读操作能够侦测到在其他 gorountine 中对改变量的写操作” 的条件。

happen-before定义

To specify the requirements of reads and writes, we define happens before, a partial order on the execution of memory operations in a Go program. If event e1 happens before event e2, then we say that e2 happens after e1. Also, if e1 does not happen before e2 and does not happen after e2, then we say that e1 and e2 happen concurrently.

这是 Happens Before 的定义,如果 e1 发生在 e2 之前,那么我们就说 e2 发生在 e1 之后,如果 e1 既不在 e2 前,也不在 e2 之后,那我们就说这俩是并发的.

关于channel的happens-before在Go的内存模型中提到了三种情况:

  • case1: 对一个channel的发送操作 happens-before 相应channel的接收操作完成
  • case2: 关闭一个channel happens-before 从该Channel接收到最后的返回值0
  • case3: 不带缓冲的channel的接收操作 happens-before 相应channel的发送操作之前
case1:对一个channel的发送操作 happens-before 相应channel的接收操作完成

测试代码:

代码语言:javascript
复制
import "testing"

var c = make(chan int, 10)
var a string

func f() {
 a = "hello, world" // (1)
 c <- 0             // (2) 写操作 发送操作
}
func TestMemoryModel(t *testing.T) {
 go f()
 <-c      // (3) //接收操作
 print(a) // (4)
}

上面的代码,将保证会打印出 hello world 。 有缓冲 channel 写操作发生在接收操作之前。

不带缓冲的channel的接收操作 happens-before 相应channel的发送操作之前

代码语言:javascript
复制
var c1 = make(chan int)
var a1 string

func f1() {
 a1 = "hello, world" // (1)
 <-c1                // (2) 接收操作
}

func TestMemoryModel1(t *testing.T) {
 go f1()
 c1 <- 0   // (3) 发送操作
 print(a1) // (4)
}

运行结果:

代码语言:javascript
复制
=== RUN   TestMemoryModel1
hello, world--- PASS: TestMemoryModel1 (0.00s)
PASS

上面的代码将保证会打印出 hello world 。 因为

根据上面的第三条规则(2) happens-before (3),最终可以保证(1) happens-before (4)。

无缓冲 channel 接收操作发生在写操作之前。

再看个例子
代码语言:javascript
复制
var c2= make(chan int, 1)
var a2 string
func f2() {
 a2 = "hello, world"  // (1)
 <-c2   //  接收操作
}
// 不能保证 打印出 "hello, world"
func TestMemoryModel2(t *testing.T) {
 go f2()
 c2 <- 0  // (3)
 print(a2)  // (4)  写操作
 //var day  time.Time
 //print(day.Format("20060102"))
}

上面的代码不能保证打印出 hello world , 因为输出的channel 是有缓冲的,不能保证接收操作发生在写操作之前,但是能保证写操作发生在接收操作之前。

欢迎关注公众号:程序员财富自由之路
参考资料
  • https://golang.org/ref/mem
  • https://lailin.xyz/post/go-training-week3-go-memory-model.html
  • https://www.jdon.com/concurrent/golang-memory.html

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 内存模型
  • happen-before定义
    • case1:对一个channel的发送操作 happens-before 相应channel的接收操作完成
    • 不带缓冲的channel的接收操作 happens-before 相应channel的发送操作之前
      • 再看个例子
        • 欢迎关注公众号:程序员财富自由之路
          • 参考资料
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档