dt614037527 2017-08-14 21:32
浏览 34

我靠运气解决的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!")
}
  • 写回答

0条回答 默认 最新

    报告相同问题?

    悬赏问题

    • ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?
    • ¥15 求daily translation(DT)偏差订正方法的代码
    • ¥15 js调用html页面需要隐藏某个按钮
    • ¥15 ads仿真结果在圆图上是怎么读数的
    • ¥20 Cotex M3的调试和程序执行方式是什么样的?
    • ¥20 java项目连接sqlserver时报ssl相关错误
    • ¥15 一道python难题3
    • ¥15 牛顿斯科特系数表表示
    • ¥15 arduino 步进电机
    • ¥20 程序进入HardFault_Handler