dtxq82489 2019-05-27 03:36
浏览 16
已采纳

使用通道限制活动Go例程的数量

I'm reading the "The Go Programming Language" One way to limit the number of running go routines is to use a "counting semaphore".

The other way is Limiting number of go routines running

I am allowing 2 more go routines in the case. I'm getting deadlock error. What causes the deadlock in my code?

package main

import (
    "bytes"
    //"context"
    "fmt"
    "runtime"
    "strconv"
    "sync"
    "time"
)

func main() {
    max := 2
    var wg sync.WaitGroup
    squares := make(chan int)
    tokens := make(chan struct{}, max)
    for i := 20; i >= 1; i-- {
        tokens <- struct{}{}
        wg.Add(1)
        go func(n int) {
            defer func() { <-tokens }()
            defer wg.Done()
            fmt.Println("run go routine ", getGID())
            squares <- Square(n)

        }(i)
    }

    go func() {
        wg.Wait()
        close(squares)
    }()

    for s := range squares {
        fmt.Println("Get square: ", s)

    }
}

func Square(num int) int {
    time.Sleep(time.Second * time.Duration(num))
    fmt.Println(num * num)
    return num * num
}

func getGID() uint64 {
    b := make([]byte, 64)
    b = b[:runtime.Stack(b, false)]
    b = bytes.TrimPrefix(b, []byte("goroutine "))
    b = b[:bytes.IndexByte(b, ' ')]
    n, _ := strconv.ParseUint(string(b), 10, 64)
    return n
}
  • 写回答

1条回答 默认 最新

  • doubi4491 2019-05-27 03:47
    关注

    The goroutines block on sending to squares. Main is not receiving on squares because it blocks on starting the the goroutines.

    Fix by moving the code that starts the goroutines to a goroutine. This allows main to continue executing to the receive on squares.

    squares := make(chan int)
    go func() {
        max := 2
        var wg sync.WaitGroup
        tokens := make(chan struct{}, max)
        for i := 20; i >= 1; i-- {
            tokens <- struct{}{}
            wg.Add(1)
            go func(n int) {
                defer func() { <-tokens }()
                defer wg.Done()
                fmt.Println("run go routine ", getGID())
                squares <- Square(n)
    
            }(i)
        }
    
        wg.Wait()
        close(squares)
    }()
    
    fmt.Println("About to receive")
    for s := range squares {
        fmt.Println("Get square: ", s)
    
    }
    

    Run it on the playground.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?