21-并发

知识列表

  • goroutine
  • channel
  • close(ch1) 关闭通道

goroutine

goroutine 是轻量级线程,goroutine 的调度是由 Golang 运行时进行管理的。

语法格式

go 函数名( 参数列表 )
go f(x, y, z)

channel

通道相关操作:初始化、发送、接收和关闭

Don’t communicate by sharing memory; share memory by communicating.
(不要通过共享内存来通信,而应该通过通信来共享内存。)

channel 相当于先进先出(FIFO)的队列

发送方: 元素值从通道进入外界时会被移动。这个移动操作实际上包含了两步, - 第一步是生成正在通道中的这个元素值的副本,并准备给到接收方, - 第二步是删除在通道中的这个元素值。

接收方: 接收操作通常包含了“复制通道内的元素值”“放置副本到接收方”“删掉原值”三个步骤。

分类

  • 单向通道
  • 双向通道

    var uselessChan = make(chan<- int, 1)
    

单向通道作用:

单向通道最主要的用途就是约束其他代码的行为。

注意 对于值为nil的通道,不论它的具体类型是什么,对它的发送操作和接收操作都会永久地处于阻塞状态。它们所属的 goroutine 中的任何代码,都不再会被执行。

注意,由于通道类型是引用类型,所以它的零值就是nil。换句话说,当我们只声明该类型的变量但没有用make函数对它进行初始时,该变量的值就会是nil。我们一定不要忘记初始化通道!

示例3

var ch3 chan int
//ch3 <- 1 // 通道的值为nil,因此这里会造成永久的阻塞!
//<-ch3 // 通道的值为nil,因此这里会造成永久的阻塞!
_ = ch3

总结
今天我们讲到了通道的一些常规操作,包括初始化、发送、接收和关闭。通道类型是 Go 语言特有的,所以你一开始肯定会感到陌生,其中的一些规则和奥妙还需要你铭记于心,并细心体会。 首先是在初始化通道时设定其容量的意义,这有时会让通道拥有不同的行为模式。对通道的发送操作和接收操作都有哪些基本特性,也是我们必须清楚的。 这涉及了它们什么时候会互斥,什么时候会造成阻塞,什么时候会引起 panic,以及它们收发元素值的顺序是怎样的,它们是怎样保证元素值的完整性的,元素值通常会被复制几次,等等。 最后别忘了,通道也是 Go 语言的并发编程模式中重要的一员。

select 执行 case 顺序:

会先执行每一个case,最后采用wei随机算法,分配相关case, 通过break 结束case通道(要注意for情况)

思考题:

https://time.geekbang.org/column/article/14664?utm_source=weibo&utm_medium=xuxiaoping&utm_campaign=promotion&utm_content=columns 如果在select语句中发现某个通道已关闭,那么应该怎样屏蔽掉它所在的分支? 在select语句与for语句联用时,怎样直接退出外层的for语句?

  1. 如果在select语句中发现某个通道已关闭,那么应该怎样屏蔽掉它所在的分支? 答:很简单,把nil赋给代表了这个通道的变量就可以了。如此一来,对于这个通道(那个变量)的发送操作和接收操作就会永远被阻塞。
  2. 在select语句与for语句联用时,怎样直接退出外层的for语句? 答:这一般会用到goto语句和标签(label),具体请参看 Go 语言规范的这部分。