代码之家  ›  专栏  ›  技术社区  ›  kramer65

为什么我有一个死锁,即使它包含一个无休止的循环?

  •  -1
  • kramer65  · 技术社区  · 7 年前

    所以我开始玩弄围棋,我对围棋的常规动作很着迷。我现在写了一个简单的测试,看看我是否可以在不断打印变量的同时更改它的值。

    我现在有以下代码:

    package main
    
    import (
        "fmt"
        "time"
    )
    
    func change(c chan float64) float64 {
        time.Sleep(2 * time.Second)
        return 2.5
    }
    
    func main() {
    
        s := 1.1
    
        c := make(chan float64)
        go change(c)
        s = <-c
    
        for {
            fmt.Println(s)
            time.Sleep(100 * time.Millisecond)
        }    
    }
    

    不幸的是,它以一个错误结束:

    fatal error: all goroutines are asleep - deadlock!
    
    goroutine 1 [chan receive]:
    main.main()
            /home/kramer65/repos/go/src/messing_around/main.go:19 +0x7d
    exit status 2
    

    有谁能告诉我这段代码有什么问题,以及我如何在不断打印的同时更改变量的值?欢迎所有提示!

    1 回复  |  直到 7 年前
        1
  •  1
  •   poy    7 年前

    该行:

    go change(c)
    

    change c . 然而,它在一段时间后返回一个值。

    此值( 2.5 )哪儿也收不到。而且 什么地方都没有写。我怀疑你是故意的 2.5 写入频道 . 其语法如下所示:

    c<-2.5
    

    因此,如果你改变你的 职能是:

    func change(c chan float64) {
        time.Sleep(2 * time.Second)
        c <- 2.5
    }
    

    你不应该再看到死锁了。请注意,我没有返回 float64 不再

    我建造了一个游乐场,以确保: https://play.golang.org/p/SgLiUmPpcAZ

    更新以供评论

    1.1 将始终被通道的值覆盖。如果你想打印 s 的初始值(如注释中所述),您必须稍微更改流并使用 select 声明:

    package main
    
    import (
        "fmt"
        "time"
    )
    
    func change(c chan float64) {
        time.Sleep(2 * time.Second)
        c <- 2.5
    }
    
    func main() {
    
        s := 1.1
    
        c := make(chan float64)
        go change(c)
    
        for {
            select {
            case s = <-c:
            default:
                // c isn't ready yet
            }
            fmt.Println(s)
            time.Sleep(100 * time.Millisecond)
        }
    }
    

    语句,您可以将其与 time.Ticker 也:

    ticker := time.NewTicker(100 * time.Millisecond)
    for {
        select {
        case s = <-c:
        case <-ticker.C:
            fmt.Println(s)
        default:
            // c isn't ready yet
        }
    }