Go каналы, кажется, не блокируют, хотя должны быть - PullRequest
0 голосов
/ 05 января 2020

Я новичок в golang и с трудом понимаю, как работают каналы. Насколько я понимаю, по умолчанию каналы должны блокироваться, поэтому я ожидаю, что планировщик, который записывает данные в канал, будет заморожен планировщиком до тех пор, пока другая программа не прочитает содержимое канала. Поэтому я попробовал следующий код, который дает соответствующий вывод:

package main

import (
    "fmt"
    "sync"
)

var wg sync.WaitGroup
var v int

func main() {
    ch := make(chan string)
    wg.Add(2)
    go func(ch chan string) {
        fmt.Println("Ready to receive")
        for msg := range ch {
            fmt.Println("received: ", msg)
            fmt.Println(v)
        }
        wg.Done()
    }(ch)
    go func(ch chan string) {
        fmt.Println("Will send the SMS to mama")
        ch <- "msg 1"
        v += 1
        fmt.Println("Done! sent the message 1")
        ch <- "msg 2"
        v += 1
        fmt.Println("Done! sent the message 2")
        ch <- "msg 3"
        v += 1
        fmt.Println("Done! sent the message 3")
        close(ch)
        wg.Done()
    }(ch)

    wg.Wait()
}

output:

Will send the SMS to mama
Ready to receive
received:  msg 1
0
Done! sent the message 1
Done! sent the message 2
received:  msg 2
2
received:  msg 3
2
Done! sent the message 3

Я немного удивлен, ожидая следующий порядок:

  1. msg 1 отправлено
  2. msg 1 получено
  3. msg 2 отправлено
  4. msg 2 получено

и так далее. Но это явно не тот случай.

Кто-нибудь имеет представление о том, почему Go ведет себя так? Большое спасибо,

Вот ссылка на код https://play.golang.org/p/O6SXf0CslPf. И вот мои источники для утверждения того, что я сказал ранее: https://medium.com/rungo/anatomy-of-channels-in-go-concurrency-in-go-1ec336086adb https://rakyll.org/scheduler/

1 Ответ

3 голосов
/ 05 января 2020

Это абсолютно нормальное поведение, поэтому я отвечаю на ваш вопрос

, поэтому я ожидаю, что планировщик заблокирует запись программы в канал до тех пор, пока другая программа не прочитает содержимое канала

Schedular может продолжать или не продолжать ту же самую процедуру после отправки значения по каналу, если не требуется дополнительная синхронизация.

Так, например, после того, как «msg 2» отправляется на ch и читается в другая последовательность в следующей строке

ch <- "msg 2"

Программа может продолжить выполнение v += 1 и вызвать fmt.Println до того, как другие программы вызовут ее.

Также вызывает fmt.Println из разных программ требует синхронизации и, возможно, mutex вызовов, что также может изменить порядок операторов печати. ​​

Более того, в переменной v

происходит скачок данных.
...