golang channel无缓冲通道会发生阻塞的验证
公司搞了午间技术par,本周我讲的主题是关于无缓冲通道channel是否会发生阻塞,并进行了验证。
go语言中channel分为无缓冲通道和有缓冲通道两种
channel提供了一种在goroutine之间共享数据的简单方法。
废话少说借用William Kennedy 打球的例子,代码如下:
C:\Users\Administrator>go version 版本信息如下:
go version go1.9 windows/amd64
// This sample program demonstrates how to use an unbuffered // channel to simulate a game of tennis between two goroutines. package main import ( "fmt" "math/rand" "sync" "time" ) // wg is used to wait for the program to finish. var wg sync.WaitGroup func init() { rand.Seed(time.Now().UnixNano()) } // main is the entry point for all Go programs. func main() { // Create an unbuffered channel. court := make(chan int) // Add a count of two, one for each goroutine. wg.Add(2) // Launch two players. go player("Nadal", court) go player("Djokovic", court) // Start the set. court <- 1 // Wait for the game to finish. wg.Wait() } // player simulates a person playing the game of tennis. func player(name string, court chan int) { // Schedule the call to Done to tell main we are done. defer wg.Done() for { // Wait for the ball to be hit back to us. ball, ok := <-court if !ok { // If the channel was closed we won. fmt.Printf("Player %s Won\n", name) return } // Pick a random number and see if we miss the ball. n := rand.Intn(100) if n%13 == 0 { fmt.Printf("Player %s Missed\n", ``) // Close the channel to signal we lost. close(court) return } // Display and then increment the hit count by one. fmt.Printf("Player %s Hit %d\n", name, ball) ball++ // Hit the ball back to the opposing player. court <- ball } }
为了验证无缓冲通道是否会阻塞,注释go player("Djokovic", court) 且将wg.Add(1)修改成1,因为只有1个go routinue要运行,如果不阻塞程序将可以正常运行,修改后的程序如下
// This sample program demonstrates how to use an unbuffered // channel to simulate a game of tennis between two goroutines. package main import ( "fmt" "math/rand" "sync" "time" ) // wg is used to wait for the program to finish. var wg sync.WaitGroup func init() { rand.Seed(time.Now().UnixNano()) } // main is the entry point for all Go programs. func main() { // Create an unbuffered channel. court := make(chan int) // Add a count of two, one for each goroutine. wg.Add(2) // Launch two players. go player("Nadal", court) //go player("Djokovic", court) // Start the set. court <- 1 // Wait for the game to finish. wg.Wait() } // player simulates a person playing the game of tennis. func player(name string, court chan int) { // Schedule the call to Done to tell main we are done. defer wg.Done() for { // Wait for the ball to be hit back to us. ball, ok := <-court if !ok { // If the channel was closed we won. fmt.Printf("Player %s Won\n", name) return } // Pick a random number and see if we miss the ball. n := rand.Intn(100) if n%13 == 0 { fmt.Printf("Player %s Missed\n", ``) // Close the channel to signal we lost. close(court) return } // Display and then increment the hit count by one. fmt.Printf("Player %s Hit %d\n", name, ball) ball++ // Hit the ball back to the opposing player. court <- ball } }
运行结果:
Player Nadal Hit 1 fatal error: all goroutines are asleep - deadlock! goroutine 1 [semacquire]: sync.runtime_Semacquire(0x56e00c) D:/Program Files/GO/src/runtime/sema.go:56 +0x40 sync.(*WaitGroup).Wait(0x56e000) D:/Program Files/GO/src/sync/waitgroup.go:131 +0x79
再次修改程序将court := make(chan int) 改成court := make(chan int,1)有缓冲
// This sample program demonstrates how to use an unbuffered // channel to simulate a game of tennis between two goroutines. package main import ( "fmt" "math/rand" "sync" "time" ) // wg is used to wait for the program to finish. var wg sync.WaitGroup func init() { rand.Seed(time.Now().UnixNano()) } // main is the entry point for all Go programs. func main() { // Create an unbuffered channel. court := make(chan int,1) // Add a count of two, one for each goroutine. wg.Add(1) // Launch two players. go player("Nadal", court) //go player("Djokovic", court) // Start the set. court <- 1 // Wait for the game to finish. wg.Wait() } // player simulates a person playing the game of tennis. func player(name string, court chan int) { // Schedule the call to Done to tell main we are done. defer wg.Done() for { // Wait for the ball to be hit back to us. ball, ok := <-court if !ok { // If the channel was closed we won. fmt.Printf("Player %s Won\n", name) return } // Pick a random number and see if we miss the ball. n := rand.Intn(100) if n%13 == 0 { fmt.Printf("Player %s Missed\n", ``) // Close the channel to signal we lost. close(court) return } // Display and then increment the hit count by one. fmt.Printf("Player %s Hit %d\n", name, ball) ball++ // Hit the ball back to the opposing player. court <- ball } }
运行结果:
Player Nadal Hit 1 Player Nadal Hit 2 Player Nadal Hit 3 Player Nadal Hit 4 Player Missed
结论:
无缓冲的通道会发生阻塞
golang channel无缓冲通道会发生阻塞的验证的更多相关文章
- Golang并发编程有缓冲通道和无缓冲通道(channel)
无缓冲通道 是指在接收前没有能力保存任何值得通道.这种类型的通道要求发送goroutine和接收goroutine同时准备好,才能完成发送和接收操作.如果两个goroutine没有同时准备好,通道会导 ...
- [GO]无缓冲通道(unbuffered channel)
无缓冲通道(unbuffered channel)是指在接收前没有能力保存任何值的通道,在之前的例子中使用的都是无缓冲通道,需要注意的是,对于无缓冲通道而言,不管是往通道里写数据还是从通道里读数据,都 ...
- [Go] golang无缓冲通道实现工作池控制并发
展示如何使用无缓冲的通道创建一个goroutine池,控制并发频率1.无缓冲通道保证了两个goroutine之间的数据交换2.当所有的goroutine都忙的时候,能够及时通过通道告知调用者3.无缓冲 ...
- golang中为何在同一个goroutine中使用无缓冲通道会导致死锁
package main import "fmt" func main() { /* 以下程序会导致死锁 c := make(chan int) c <- 10 n1 := ...
- Go语言的通道(1)-无缓冲通道
前言: 上文中我们采用了[原子函数]已经[共享锁]两种方式分别对多个goroutine进行了同步,但是在go语言中提供了另一种更好的方式,那就是使用通道(Channel). 一.通道是什么? 其实无论 ...
- go无缓冲通道
package main import ( "fmt" "math/rand" "sync" "time" ) //wg ...
- Go语言有缓冲和无缓冲通道实现样例
感觉可以,但不好用. 应该有封装程序更高的包包吧. package main import ( "math/rand" "fmt" "time&quo ...
- golang的缓冲channel和无缓冲channel的区别
话说golang的channel同步的定义真是让人无力吐槽,码农的用户体验就这么难搞么,超耐磨阿,无缓冲和缓冲居然有这么大区别....靠 转载一段网上的资料 --------------------- ...
- go之无缓冲channel(通道)和有缓冲channel(通道)
channel我们先来看一下通道的解释:channel是Go语言中的一个核心类型,可以把它看成管道.并发核心单元通过它就可以发送或者接收数据进行通讯,这在一定程度上又进一步降低了编程的难度.chann ...
随机推荐
- SSM整合学习笔记
对学习Spring+Spring MVC+Mybatis过程中出现的问题解决办法汇总 出现的问题 1.pom.xml报错 右键项目->maven->update project 因此每次更 ...
- (转)centos7安装telnet服务
场景:在进行Telnet测试时候,发现无法连接,所以还得把这个软件也安装了 1 CentOS7.0 telnet-server 启动的问题 解决方法: 先检查CentOS7.0是否已经安装以下两个 ...
- 【JAVASCRIPT】React学习- 数据流(组件通信)
摘要 react 学习包括几个部分: 文本渲染 JSX 语法 组件化思想 数据流 一 组件通信如何实现 父子组件之间不存在继承关系 1.1 父=>子通信 父组件可以通过 this.refs.xx ...
- 从Ubunt的安装到hadoop集群的搭建
一.相关基础配置 1.网络设置 a.调整VMnet8这块网卡网关 b.在VMware[编辑]->[虚拟网络编辑器]对VMnet8进线[NAT 设置] c.调整[DHCP 设置]中的起始IP地址 ...
- github 或者gitlab 设置添加SSH
克隆项目二种方式: 1. 使用https url克隆, 复制https url 然后到 git clone https-url 2.使用 SSH url 克隆却需要在克隆之前先配置和添加好 SSH ...
- 调皮的QQ音乐API:修复无法获取歌单
上一篇完整版:http://www.cnblogs.com/TwilightLemon/p/7076938.html QQ音乐的API真是太调皮了,获取歌单的API又更换了好多次,喵喵喵 旧版API( ...
- Samba服务部署
Samba,是种用来让UNIX系列的操作系统与微软Windows操作系统的SMB/CIFS(Server Message Block/Common Internet File System)网络协议做 ...
- CodeForces 816B Karen and Coffee(前缀和,大量查询)
CodeForces 816B Karen and Coffee(前缀和,大量查询) Description Karen, a coffee aficionado, wants to know the ...
- 简陋的 ASP.NET CORE 单页Web应用程序“框架”
我对ASP.NET CORE了解不多,不知道是不是重复造轮子,也或者什么也不是,这个Demo是这样的: 1.非常简单或者说原始:2.将单页Web应用增加了一个页(Page)概念(相当于MVC的 Vie ...
- 又见angular----步一步做一个angular4小项目
这两天看了看angular4的文档,发现他和angular1.X的差别真的是太大了,官方给出的那个管理英雄的Demo是一个非常好的入门项目,这里给出一个管理个人计划的小项目,从头至尾一步一步讲解如何去 ...