go channel

send被执行前(proceed)通讯(communication)一直被阻塞着。如前所言,无缓存的channel只有在receiver准备好后send才被执行。如果有缓存,并且缓存未满,则send会被执行。

往一个已经被close的channel中继续发送数据会导致run-time panic

往nil channel中发送数据会一致被阻塞着。

  1. receive 操作符
    <-ch用来从channel ch中接收数据,这个表达式会一直被block,直到有数据可以接收。

从一个nil channel中接收数据会一直被block。

从一个被close的channel中接收数据不会被阻塞,而是立即返回,接收完已发送的数据后会返回元素类型的零值(zero value)。

如前所述,你可以使用一个额外的返回参数来检查channel是否关闭。

 

1

2

3

 

x, ok := <-ch

x, ok = <-ch

var x, ok = <-ch

如果OK 是false,表明接收的x是产生的零值,这个channel被关闭了或者为空。

 

Happens Before的作用

Happens Before主要是用来保证内存操作的可见性。如果要保证E1的内存写操作能够被E2读到,那么需要满足:

  1. E1 Happens Before E2;
  2. 其他所有针对此内存的写操作,要么Happens Before E1,要么Happens After E2。也就是说不能存在其他的一个写操作E3,这个E3 Happens Concurrently E1/E2。

为什么需要定义Happens Before关系来保证内存操作的可见性呢?原因是没有限制的情况下,编译器和CPU使用的各种优化,会对此造成影响,具体的来说就是操作重排序和CPU CacheLine缓存同步:

  • 操作重排序。现代CPU通常是流水线架构,且具有多个核心,这样多条指令就可以同时执行。然而有时候出现一条指令需要等待之前指令的结果,或是其他造成指令执行需要延迟的情况。这个时候可以先执行下一条已经准备好的指令,以尽可能高效的利用CPU。操作重排序可以在两个阶段出现:
    • 编译器指令重排序
    • CPU乱序执行
  • CPU 多核心间独立Cache Line的同步问题。多核CPU通常有自己的一级缓存和二级缓存,访问缓存的数据很快。但是如果缓存没有同步到主存和其他核心的缓存,其他核心读取缓存就会读到过期的数据。

 

声明但不make初始化的chan是nil chan。读写nil chan会阻塞,关闭nil chan会panic。

写closed chan或关闭 closed chan会导致panic。读closed chan永远不会阻塞,会返回一个通道数据类型的零值。

 

channel happens-before:

  • 对带缓冲chan的写操作 happens-before相应chan的读操作
  • 关闭chan happens-before 从该chan读最后的返回值0
  • 不带缓冲的chan的读操作 happens-before相应chan的写操作
var c = make(chan int, 10)
var a string
func f() {
  a = "hello, world"  //(1)
  c <- 0  // (2)
}

func main() {
  go f()
  <- c  //(3)
  print(a)  //(4)
}

(1) happens-before(2) (3) happens-before(4),再根据规则可知(2) happens(3)。因此(1)happens-before(4),这段代码没有问题,肯定会输出hello world。

var c = make(chan int)
var a string
func f() {
  a = "hello, world"  //(1)
  <-c  // (2)
}

func main() {
  go f()
  c <- 0  //(3)
  print(a)  //(4)
}

同样根据规则三可知(2)happens-before(3) 最终可以保证(1) happens-before(4)。若c改成待缓冲的chan,则结果将不再有任何同步保证使得(2) happens-before(3)。

 

参考:

https://zhuanlan.zhihu.com/p/29108170

https://ninokop.github.io/2017/11/07/Go-Channel%E7%9A%84%E5%AE%9E%E7%8E%B0/

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值