Использование блокировки Mutex - все еще тупик - PullRequest
0 голосов
/ 09 мая 2019

Я играю с Goroutines и каналами и удивляюсь, почему я получил ошибку в названии.
Идея состоит в том, что у меня есть один глобальный int-канал, который увеличивается на каждую маршрутизацию.
Используя блокировку мьютекса, я ожидал, что канал будет заблокирован для каждой процедуры, но это не удалось.
Код здесь:

package main

import (
    "fmt"
    "sync"
)

var number = make(chan int)
var mutex = &sync.Mutex{}

func worker(wg *sync.WaitGroup, id int) {
    defer wg.Done()

    mutex.Lock()
    number <- id + <-number
    mutex.Unlock()
}

func main() {
    var wg sync.WaitGroup
    number <- 0
    for i := 0; i < 5; i++ {
        wg.Add(1)
        go worker(&wg, i)
    }

    wg.Wait()
    fmt.Println(<-number) // expected output: 0+1+2+3+4 = 10
}

https://play.golang.org/p/P5P9Bf5ZSIP

1 Ответ

3 голосов
/ 09 мая 2019

Проблема здесь связана с тем каналом, который вы используете, поскольку он небуферизован.Небуферизованный канал будет блокироваться до тех пор, пока не будет получатель для получения сообщения.

Здесь основная процедура go добавляет номер в канал, затем создает процедуры 5 go, чтобы снять канал и затем добавить в канал.ждет их завершения, прежде чем убрать предмет с канала.Добавление 0 к каналу не будет происходить до тех пор, пока не будет чего-то, что получит от него номер, поэтому оно блокируется, прежде чем оно даже достигнет мьютекса.

Процедуры 5 go могут завершиться, только если что-то снимает что-то сchannel.

Если вы переключитесь на буферизованный канал, указав размер для вызова make, то он начнет выполняться до завершения:

package main

import (
    "fmt"
    "sync"
)

var number = make(chan int, 5)
var mutex = &sync.Mutex{}

func worker(wg *sync.WaitGroup, id int) {
    defer wg.Done()

    mutex.Lock()
    number <- id + <-number
    mutex.Unlock()
}

func main() {
    var wg sync.WaitGroup
    number <- 0
    for i := 0; i < 5; i++ {
        wg.Add(1)
        go worker(&wg, i)
    }

    wg.Wait()
    fmt.Println(<-number) // expected output: 0+1+2+3+4 = 10
}

https://play.golang.org/p/QDXuDH0RGPC

...