专栏首页程序员财富自由之路Go 语言 chanel 内存模型
原创

Go 语言 chanel 内存模型

内存模型

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的接收操作完成

测试代码:

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的发送操作之前

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)
}

运行结果:

=== RUN   TestMemoryModel1
hello, world--- PASS: TestMemoryModel1 (0.00s)
PASS

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

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

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

再看个例子

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

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

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

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Go 语言中 channel 内存模型

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

    王小明_HIT
  • Go语言Goroutine与Channel内存模型

    Go语言内存模型规定了在一个goroutine中一个变量的读取的情况下,确保能够观察到在其他另外goroutine中写入同样变量的值。也就是说,如果在多个gor...

    李海彬
  • Go语言Goroutine与Channel内存模型

    Go语言内存模型规定了在一个goroutine中一个变量的读取的情况下,确保能够观察到在其他另外goroutine中写入同样变量的值。也就是说,如果在多个gor...

    李海彬
  • Go语言Goroutine与Channel内存模型

    Go语言内存模型规定了在一个goroutine中一个变量的读取的情况下,确保能够观察到在其他另外goroutine中写入同样变量的值。也就是说,如果在多个gor...

    李海彬
  • 面经--微博&&今日头条

    牛客网
  • Go语言实战-2

    Go语言解决的问题:C和C++执行速度快,Python擅长快速开发,Go兼具二者特点。

    皮大大
  • C语言内存模型

    用户2929716
  • Golang 语言的内存模型

    Go 内存模型可以保证一个 goroutine 可以读取在不同 goroutine 中修改同一指定变量的值。

    frank.
  • [转] 编程语言内存模型

    这是Russ Cox的第二篇Programming Language Memory Models。

    麒思妙想
  • Go内存模型

    Go语言中内存分配大致有3种模式:Stack、Heap、Fixed Size Segment。

    后台搬砖鹅
  • Go 语言内存管理(二):Go 内存管理

    了解操作系统对内存的管理机制后,现在可以去看下 Go 语言是如何利用底层的这些特性来优化内存的。Go 的内存管理基本上参考 tcmalloc 来实现的,只是细节...

    李海彬
  • Golang之旅3-基本数据类型

    GO语言中的数据类型十分丰富,包含:整型、浮点型、布尔型,还有数组、切片、结构体、函数、map、通道chanel等

    皮大大
  • Golang之旅12-指针

    变量是一种使用方便的占位符,用于引用计算机内存地址。Go 语言的取地址符是 &,放到一个变量前使用就会返回相应变量的内存地址。另外一个符号是*,表示的是根据地址...

    皮大大
  • Go 笔记之如何防止 goroutine 泄露

    Go 的并发模型与其他语言不同,虽说它简化了并发程序的开发难度,但如果不了解使用方法,常常会遇到 goroutine 泄露的问题。虽然 goroutine 是轻...

    波罗学
  • 图解Go语言内存分配

    Go语言内置运行时(就是runtime),抛弃了传统的内存分配方式,改为自主管理。这样可以自主地实现更好的内存使用模式,比如内存池、预分配等等。这样,不会每次内...

    梦醒人间
  • 图解Go语言内存分配

    Go语言内置运行时(就是runtime),抛弃了传统的内存分配方式,改为自主管理。这样可以自主地实现更好的内存使用模式,比如内存池、预分配等等。这样,不会每次内...

    老钱
  • 图解Go语言内存分配

    Go语言内置运行时(就是runtime),抛弃了传统的内存分配方式,改为自主管理。这样可以自主地实现更好的内存使用模式,比如内存池、预分配等等。这样,不会每次内...

    李海彬
  • Go 语言内存管理(一):系统内存管理

    要搞明白 Go 语言的内存管理,就必须先理解操作系统以及机器硬件是如何管理内存的。因为 Go 语言的内部机制是建立在这个基础之上的,它的设计,本质上就是尽可能的...

    李海彬
  • 【Go 语言 redis内存数据库存储 demo】

    package main import ( "fmt" "github.com.Go-Redis/github.com/alph...

    李海彬

扫码关注云+社区

领取腾讯云代金券