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 ...
随机推荐
- Android 自定义 permission
Android 自定义 permission Android 添加自定义权限 permission-tree 权限的根节点,3个成员都要定义 name 一般来说需要2个".":比如 ...
- PHP对MySQL数据库的相关操作
一.Apache服务器的安装 <1>安装版(计算机相关专业所用软件---百度云链接下载)-直接install<2>非安装版(https://www.apachehaus.com ...
- koa2 use里面的next到底是什么
koa2短小精悍,女人不爱男人爱. 之前一只有用koa写一点小程序,自认为还吼吼哈,知道有一天某人问我,你说一下 koa或者express中间件的实现原理.然后我就支支吾吾,好久吃饭都不香. 那么了解 ...
- Python学习记录----类型匹配(转)
import types aaa = 0 print type(aaa) if type(aaa) is types.IntType: print "the type of aaa is i ...
- matrix()方法与translate()、scale()、rotate()、skew()方法的关系
2D变换方法translate().scale().rotate().skew()与matrix()的关系举例介绍. 一.介绍 2D变换方法: translate():根据左(X轴)和顶部(Y轴)位置 ...
- web组件工具之获取表单数据:webUtils
本文需要的架包:commons-beanutils-1.8.3.jar.commons-logging-1.1.3.jar.servlet-api.jar. 本文共分为五部分:1)封装通用工具类:从表 ...
- 移动端 transitionEnd函数用来检测过渡是否完成
注意的几点:兼容 'webkitTransitionEnd' 解绑 renmove tab_wrap.addEventListener('transitionEnd',transitionEnd); ...
- ServletAPI的获取
Action中获取ServletAPI,三种方式 (1)通过ActionContext获取(只是获取并操作了域空间,并不是真正的ServletAPI对象) 在struts2框架中,通过Action的执 ...
- 一次花费了一两个小时的mysql问题排查
晚上把博客迁了个服务器,新建用户的时候遇到问题了. 关于mysql的问题. 前置操作 建了两个用户,一个laravel,一个blog用户以及他们的同名数据库. 建好之后,命令行下面连接mysql服务, ...
- Grass Cownoisseur[Usaco2015 Jan]
题目描述 In an effort to better manage the grazing patterns of his cows, Farmer John has installed one-w ...