我靠运气解决的Golang僵局,需要说明
I'm trying to understand go channel and go routine. To do so, I'm doing online exercises. I found one here: http://whipperstacker.com/2015/10/05/3-trivial-concurrency-exercises-for-the-confused-newbie-gopher/
I resolved the 3rd one (named "Internet cafe"). But there's something I resolved by "luck", and it's bother me because I don't understand my issue and why my "hack" fixed it.
In my code below, I replace "enterChan <- next" by "go func() { enterChan <- next }()", and it solved my deadlock.
Can someone explain to me why it deadlock before, and why it works with this hack ? Is it a proper solution, or an ugly one ?
Don't hesitate to criticize my code, I'm searching to improve :)
Many thanks!
This is my code:
package main
import (
"fmt"
"math/rand"
"strconv"
"time"
)
const (
maxNumberOfUser = 8
)
func useComputer(tourist string, leaverChan chan string) {
seed := rand.NewSource(time.Now().UnixNano())
random := rand.New(seed)
fmt.Println(tourist, "is online")
d := random.Intn(120-15) + 15
time.Sleep(time.Duration(d) * time.Millisecond * 10)
fmt.Println(tourist, "is done, having spent", d, "minutes online.")
leaverChan <- tourist
}
func manageUsers(enterChan, leaverChan chan string, stopChan chan struct{}) {
nbUsed := 0
queue := make([]string, 0)
for {
select {
case tourist := <-enterChan:
if nbUsed < maxNumberOfUser {
nbUsed++
go useComputer(tourist, leaverChan)
} else {
fmt.Println(tourist, "waiting for turn.")
queue = append(queue, tourist)
}
case tourist := <-leaverChan:
nbUsed--
fmt.Println(tourist, "is leaving, number of free place is now:", maxNumberOfUser-nbUsed)
if len(queue) > 0 {
next := queue[0]
queue = queue[1:]
go func() {
enterChan <- next
}()
} else if nbUsed == 0 {
close(stopChan)
return
}
}
}
}
func main() {
enterChan := make(chan string)
leaverChan := make(chan string)
stopChan := make(chan struct{})
go manageUsers(enterChan, leaverChan, stopChan)
for i := 1; i <= 25; i++ {
enterChan <- "Tourist " + strconv.Itoa(i)
}
<-stopChan
fmt.Println("The place is empty, let's close up and go to the beach!")
}
- 点赞
- 写回答
- 关注问题
- 收藏
- 复制链接分享
- 邀请回答
为你推荐
- Golang 如何进行标准错误输出
- Golang
- 1个回答
- 我是Golang的新手,并希望说明以下任务
- 1个回答
- 需要使用URL参数在Golang中查询Json数据
- json
- 1个回答
- 通用golang装饰器(要点说明)
- 1个回答
- 如何解决Golang中“返回的参数过多”的问题?
- 2个回答
- 我如何在Golang中将RFC3339转换为UNIX
- 1个回答
- Golang在我的视频流上超时
- 1个回答
- 我可以通过Golang将图像上传到Imgur吗
- 1个回答
- 我应该如何在golang中传递param?
- 1个回答
- 我如何排除周末golang
- 6个回答
- 我的Golang应用程序中需要一个或多个sarama.SyncProducer吗?
- 3个回答
- Golang接口不需要导入吗?
- 2个回答
- 为什么我在使用此Golang代码时陷入僵局?
- 1个回答
- 是否需要为Golang中的变量分配默认值?
- 3个回答
- 我应该直接在golang中使用ServeMux还是http
- 1个回答
- golang,如何执行需要用户输入的命令
- 1个回答
- golang main包可以被import吗
- Golang
- 2个回答
- golang小数默认是float32还是float64?
- Golang
- 2个回答
- golang const 可以修饰函数形参吗
- Golang
- 1个回答
- 使用Golang拼接ffmpeg命令之后filter错误
- Golang
- 1个回答