对 channel 进行读、写、关闭操作会怎么样 ?
本文最后更新于:2 个月前
对 channel 进行读、写、关闭操作会怎么样 ?
对 nil 的 channel 进行读和写 都会造成当前 goroutine 永久阻塞(如果当前 goroutine 是 main goroutine,则会让整个程序直接报 fatal error 退出),关闭则会发生 panic(但这里我们不要忘记,还有一种叫做非阻塞(select default )的方式操作 channel,这种模式下,就算对为 nil 的 channel 读写,也不会阻塞的)
对不为 nil,并且未关闭的 channel 操作,读和写都有两种情况:
- 读操作:
成功读取:如果 channel 中有数据,直接从 channel 里面读取,如果此时写等待队列里面有 goroutine,还需要将队列头部 goroutine 数据写入到 channel 中,并唤醒这个 goroutine;如果 channel 没有数据,就尝试从写等待队列中读取数据,并做对应的唤醒操作
(读操作无法及时完成)阻塞挂起:channel 里面没有数据 并且 写等待队列为空,则当前 goroutine 加入 读 i.等待队列中,并挂起,等待唤醒
- 写操作
成功写入:如果 channel 读等待队列不为空,则取 头部 goroutine,将数据直接复制给这个头部 i.goroutine,并将其唤醒,流程结束;否则就尝试将数据写入到 channel 环形缓冲中
(写操作无法及时完成)阻塞挂起:通道里面 buf 满了 并且 读等待队列为空,则当前 gorotine 加入写等待队 i.列中,并挂起,等待唤醒
- 读操作:
对已经关闭的 channel 进行写和关闭 都会导致 panic,而读取是直到读完 channel 中剩余数据,还想读的话,就会获得零值
select 分为两种,包含非阻塞型 select (包含 default 分支的)和阻塞型 select (不包含 default 分支的)
阻塞型:
1 |
|
非阻塞型:
1 |
|
关注我获取更新
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!