Используйте канал, чтобы ограничить количество активных подпрограмм го - PullRequest
0 голосов
/ 27 мая 2019

Я читаю «Язык программирования Go». Один из способов ограничить количество выполняемых подпрограмм go - это использовать «счетный семафор».

Другой способ - Ограничение числа goвыполнение подпрограмм

Я разрешаю еще 2 подпрограммы в этом случае.Я получаю тупиковую ошибку.Что вызывает тупик в моем коде?

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 Ответ

1 голос
/ 27 мая 2019

Блок goroutines при отправке на squares.Main не получает на squares, потому что он блокирует запуск goroutines.

Исправление путем перемещения кода, запускающего goroutines, в goroutine.Это позволяет основному продолжить выполнение приема на 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)

}

Запустить его на детской площадке .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...