所有的Go协程都处于休眠状态 – 死锁

huangapple go评论82阅读模式
英文:

all go routines are asleep - deadlock

问题

我不明白为什么在这段代码中会发生死锁。我尝试了几种不同的方法来解决死锁问题(使用了几个不同版本的WorkGroup)。这是我在Go语言中的第一天,到目前为止,我对于相当简单和直接的操作的复杂性感到非常失望。我觉得我可能错过了一些重要而明显的东西,但是我找到的所有文档似乎与我认为的非常基本的操作模式非常不同。所有的文档都使用了基本类型的通道(int、string),而不是更复杂的类型,都是使用非常基本的for循环,或者在另一端是相当复杂的函数编排。

我想我真的在寻找一个中间的示例,即“通常的做法”与goroutines。

package main

import "fmt"
import "time"

type Item struct {
    name string
}

type Truck struct {
    Cargo []Item
    name  string
}

func UnloadTrucks(c chan Truck) {
    for t := range c {
        fmt.Printf("%s has %d items in cargo: %s\n", t.name, len(t.Cargo), t.Cargo[0].name)
    }
}

func main() {
    trucks := make([]Truck, 2)
    ch := make(chan Truck)

    for i, _ := range trucks {
        trucks[i].name = fmt.Sprintf("Truck %d", i+1)
        fmt.Printf("Building %s\n", trucks[i].name)
    }

    for t := range trucks {
        go func(tr Truck) {
            itm := Item{}
            itm.name = "Groceries"
            fmt.Printf("Loading %s\n", tr.name)
            tr.Cargo = append(tr.Cargo, itm)
            ch <- tr
        }(trucks[t])
    }

    time.Sleep(50 * time.Millisecond)
    fmt.Println("Unloading Trucks")
    UnloadTrucks(ch)
    fmt.Println("Done")
}

希望对你有所帮助。

英文:

I don't understand why the deadlock is occurring in this code. I've tried several different things to get the deadlock to stop (several different versions using WorkGroup). This is my first day in Go, and I am pretty disappointed so far with the complexity of fairly simple and straightforward operations. I feel like I'm missing something big and obvious, but all of the docs I have found on this are seemingly very different from what, to me, is a very basic mode of operation. All of the docs use primitive types for channels (int, string) not more complex types, all with very basic for loops OR on they are on the other end of the spectrum where the functions are fairly complicated orchestrations.

I guess I'm really looking for a middle of the road sample of "this is how it's usually done" with goroutines.

package main

import &quot;fmt&quot;

//import &quot;sync&quot;
import &quot;time&quot;

type Item struct {
    name string
}

type Truck struct {
    Cargo []Item
    name  string
}

func UnloadTrucks(c chan Truck) {

    for t := range c {
        fmt.Printf(&quot;%s has %d items in cargo: %s\n&quot;, t.name, len(t.Cargo), t.Cargo[0].name)
    }

}

func main() {
    trucks := make([]Truck, 2)

    ch := make(chan Truck)

    for i, _ := range trucks {

        trucks[i].name = fmt.Sprintf(&quot;Truck %d&quot;, i+1)

        fmt.Printf(&quot;Building %s\n&quot;, trucks[i].name)
    }

    for t := range trucks {
        go func(tr Truck) {

            itm := Item{}
            itm.name = &quot;Groceries&quot;

            fmt.Printf(&quot;Loading %s\n&quot;, tr.name)
            tr.Cargo = append(tr.Cargo, itm)
            ch &lt;- tr

        }(trucks[t])
    }

    time.Sleep(50 * time.Millisecond)
    fmt.Println(&quot;Unloading Trucks&quot;)
    UnloadTrucks(ch)

    fmt.Println(&quot;Done&quot;)
}

答案1

得分: 6

你从未关闭 "truck" 通道 ch,所以 UnloadTrucks 永远不会返回。

你可以在所有的工作完成后关闭通道,通过使用一个 WaitGroup:

go func() {
	wg.Wait()
	close(ch)
}()
UnloadTrucks(ch)

http://play.golang.org/p/1V7UbYpsQr

英文:

You never close the "truck" channel ch, so UnloadTrucks never returns.

You can close the channel after all workers are done, by using a WaitGroup:

go func() {
	wg.Wait()
	close(ch)
}()
UnloadTrucks(ch)

http://play.golang.org/p/1V7UbYpsQr

huangapple
  • 本文由 发表于 2015年12月30日 05:43:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/34519546.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定