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

Go 语言中 channel 内存模型

内存模型

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 是有缓冲的,不能保证接收操作发生在写操作之前,但是能保证写操作发生在接收操作之前。

欢迎关注公众号:程序员财富自由之路

公众号:程序员财富自由之路

博客:CSDN 王小明

关注我们,了解更多

关注后:回复 “idea” 或者 “内推”, 有惊喜

参考资料

  • https://golang.org/ref/mem
  • https://lailin.xyz/post/go-training-week3-go-memory-model.html
  • https://www.jdon.com/concurrent/golang-memory.html

本文分享自微信公众号 - 程序员财富自由之路(gh_016ffe40d550),作者:猿星人

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2021-09-12

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Go语言Goroutine与Channel内存模型

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

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

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

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

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

    李海彬
  • Go 语言 chanel 内存模型

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

    王小明_HIT
  • Go语言中channel的用法

    channel有点类似于管道,它在goroutine同步与通信中,有着起承转合的作用,同时也是Golang实现CSP模型的关键

    会呼吸的Coder
  • C语言内存模型

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

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

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

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

    麒思妙想
  • Go内存模型

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

    后台搬砖鹅
  • 谈谈Golang并发编程

    Go语言在设计时,Java和C ++是编写服务器程序最常用的语言(至少在Google是这样),这是因为使用这些语言可以高效的开发。但是Go设计者们觉得像Java...

    加多
  • Go语言中的管道(Channel)总结

    管道(Channel)是Go语言中比较重要的部分,经常在Go中的并发中使用。今天尝试对Go语言的管道来做以下总结。总结的形式采用问答式的方法,让答案更有目的性。...

    李海彬
  • 字节跳动的 Go 语言面试会问哪些问题?

    这个一般分为两个层次,初中级开发(1-1、1-2)和高级开发(2-1、2-2),不同级别的面试一般要求是不一样的。对于初中级开发,一般会问一些语言层面的东西,一...

    肉眼品世界
  • Go 语言内存管理(二):Go 内存管理

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

    李海彬
  • 深度解密Go语言之channel

    大家好啊!“深度解密 Go 语言”系列好久未见,我们今天讲 channel,预祝阅读愉快!在开始正文之前,我们先说些题外话。

    梦醒人间
  • 【深度知识】GO语言的goroutine并发原理和调度机制

    Go语言最大的特色就是从语言层面支持并发(Goroutine),Goroutine是Go中最基本的执行单元。事实上每一个Go程序至少有一个Goroutine:主...

    辉哥
  • Go 并发实战--管道浅析

    在讲 channel 之前,有必要先提一下 CSP 模型,传统的并发模型主要分为 Actor模型和CSP模型,CSP 模型(communicating sequ...

    邹志全
  • Go的CSP并发模型实现:M, P, G

    最近抽空研究、整理了一下Golang调度机制,学习了其他大牛的文章。把自己的理解写下来。如有错误,请指正!!!

    sunsky
  • go-并发

    Go语言的并发通过 goroutine 实现。 goroutine 类似于线程,属于用户态的线程,我们可以根据需要创建成千上万个 goroutine 并发工作。...

    新人小试
  • Golang之旅23-通道channel

    在goroutine并发执行的时候,需要在函数和函数之间进行通信。Go语言并发模式CSP(communicating Sequents Processes),通...

    皮大大

扫码关注云+社区

领取腾讯云代金券