教程集 www.jiaochengji.com
教程集 >  Golang编程  >  golang教程  >  正文 golang的channel机制

golang的channel机制

发布时间:2022-01-05   编辑:jiaochengji.com
教程集为您提供golang的channel机制等资源,欢迎您收藏本站,我们将为您提供最新的golang的channel机制资源
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;"><path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"/></svg>

信道分为无缓冲信道(即unbuffered channel)和有缓冲信道(buffered channel)。对于无缓冲的信道来说,我们默认信道的发消息(send)和收消息(receive)都是阻塞(block)的。换句话来说,无缓冲的信道在收消息和发消息的时候,goroutine都处于挂起状态。除非另一端准备好,否则goroutine无法继续往下执行。

<h4>无缓冲channel</h4> <pre><code>var ch = make(chan int) func main() { ch <- 1 <-ch } </code></pre>

上面的这段程序在main函数执行到ch <- 1的时候main(也是一个goroutine)便已挂起,而并没有其他goroutine负责接收消息,而下面一句 <-ch 永远无法执行,系统便自动判为timeout返回error。这种所有线程或者进程都在等待资源释放的情况,便称之为死锁。

死锁分类:

<ol><li>只在单一goroutine里操作信道</li><li>串联信道中间一环挂起</li><li>非缓冲信道不成对出现</li></ol>

注意:并非所有不成对出现的非缓冲信道都会报错

<pre><code>func say(ch chan int) { ch <- 1 } func main() { ch := make(chan int) go say(ch) } </code></pre>

虽然say函数挂起等待信道接收消息,但是main goroutine并没有被阻塞,在main函数返回后程序依然可以自动终止。

<h4>
缓冲channel</h4> <pre><code>func main() { ch := make(chan int, 3) ch<-1 ch<-2 ch<-3 //close(ch) for value := range ch { fmt.Println(value) //if len(ch) == 0{ // break //} } } </code></pre>

上述代码在执行完毕后会报deadlock的错误,其原因在于range不会自动检测信道是否干涸(drained),在提取完全部数据后,再次提取会使main函数挂起。
解决方案也有两种,第一种是在for循环中设置长度检测,如果信道为空则跳出循环;第二种是在接收完全部数据后关闭信道。这里值得注意的一点是,关闭状态的信道永远不会阻塞。
第二种方法揭示了信道的另一个特性:对于关闭的信道无法再接收新的数据,但是可以提取其中存留的数据。

总结:
1.在goroutine里读和写channel都会阻塞
2.关闭channel后变成只读,读操作的阻塞会被释放,写操作会报错
3.在main函数里的读写channel不成对出现,会造成死锁

转自:
https://www.jianshu.com/p/147bd63801b6
https://www.jianshu.com/p/082015461b6d

到此这篇关于“golang的channel机制”的文章就介绍到这了,更多文章或继续浏览下面的相关文章,希望大家以后多多支持JQ教程网!

您可能感兴趣的文章:
Go并发编程——channel
【文末有惊喜!】一文读懂golang channel
go语言并发编程
golang的select实现原理剖析
Golang之消息机制channel
Go 语言为什么这么快,带你详细了解Golang CSP并发模型
golang的channel机制
golang知识点
Go语言并发--传统锁与channel的选择
go channel 缓冲区最大限制_Golang 入门 : channel(通道)

[关闭]
~ ~