Go синхронизация и модель параллелизма - PullRequest
0 голосов
/ 28 мая 2019

Я новичок в Go, и я слежу за gobyexample.com , чтобы изучить основы.Когда я дохожу до раздела «закрытие каналов», учебник вставляет этот фрагмент кода (я удалю оригинальные комментарии):

    package main

    import "fmt"

    func main() {
        jobs := make(chan int, 5)
        done := make(chan bool)

       go func() {
           for {
               j, more := <-jobs
               if more {
                   fmt.Println("received job", j)
               } else {
                   fmt.Println("received all jobs")
                   done <- true
                   return
               }
           }
       }()

       for j := 1; j <= 18; j++ {
           jobs <- j
           fmt.Println("sent job", j)
       }
       close(jobs)
       fmt.Println("sent all jobs")

       <-done
    }

В исходном коде в цикле отправителя задания было задано 3 вместо 18.

Выполнение этого кода в play.golang.org это то, что я не до конца понимаю.Он всегда выдает следующее:

sent job 1
sent job 2
sent job 3
sent job 4
sent job 5
received job 1
received job 2
received job 3
received job 4
received job 5
received job 6
sent job 6
sent job 7
sent job 8
sent job 9
sent job 10
sent job 11
sent job 12
received job 7
received job 8
received job 9
received job 10
received job 11
received job 12
received job 13
sent job 13
sent job 14
sent job 15
sent job 16
sent job 17
sent job 18
sent all jobs
received job 14
received job 15
received job 16
received job 17
received job 18
received all jobs

Так что я понимаю, что «очередь» канала (я знаю, что эта терминология не самая точная, но для целей изучения себя это то, что японять, что такое канал), имеет размер 5, так что первые 10 сообщений журнала подходят для меня.

Но как сообщения 6 и 13 могут быть выведены при приеме до их фактической отправки?Как можно отправить 7 сообщений подряд, если размер канала равен 5?Что я упускаю из этого?

Ответы [ 2 ]

2 голосов
/ 28 мая 2019

Запрограммированы подпрограммы одновременно, поэтому они также печатают в стандартный вывод одновременно (то есть не по порядку). Более того, API-интерфейсы fmt.Print буферизуются, поэтому ваши отпечатки на самом деле не распечатываются сразу, как они вызываются. Это происходит и на других языках.

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

2 голосов
/ 28 мая 2019

Но как сообщения 6 и 13 могут быть выведены на их прием до их фактической отправки?

Мы знаем только, что fmt.Println("received job", j) было напечатано до того, как fmt.Println("sent job", j) было напечатано, иэто возможно в параллельном рабочем коде.

Как могут быть отправлены 7 сообщений подряд, если размер канала равен 5?

Опять же, поскольку мы не знаем точно, какой оператор печатается первым, это можетбыть ожидаемым.Очередь уже может быть уменьшена, и мы все еще печатаем.

...