2017-01-23 3 views
0

Я играю с кодом, представленным на https://tour.golang.org/concurrency/5. Моя идея заключалась в том, что я мог бы упростить код, избавившись от канала quit и все еще сохраняя правильное поведение программы - только для учебных целей.Голанг параллелизм и блокировка одним каналом, необходимо объяснение

Вот код, который я получил (упрощенно его еще больше для лучшей читаемости):

package main 

import "fmt" 
import "time" 

func sendNumbers(c chan int) { 
    for i := 0; i < 2; i++ { 
     c <- i 
    } 
} 

func main() { 
    c := make(chan int) 
    go func() { 
     for i := 0; i < 2; i++ { 
      fmt.Println(<-c) 
     } 
    }() 
    time.Sleep(0 * time.Second) 
    sendNumbers(c) 
} 

В этом коде идет рутину я нерест должна быть в состоянии получить 2 номера, прежде чем он вернется. Функция sendNumbers(), которую я вызываю, отправляет ровно 2 номера в канал c.

Таким образом, ожидаемый результат программы составляет 2 линии: 0 и 1. Тем не менее, то, что я получаю, когда я бегу код на странице, просто одна строка, содержащая 0.

Примечание к

time.Sleep(0 * time.Second) 

хотя я специально добавил до вызова sendNumbers (c). Если изменить его

time.Sleep(1 * time.Second) 

Выход становится, как и ожидалось:

0 
1 

Итак, я запутался, что происходит. Может кто-нибудь объяснить, что происходит? Не следует ли отправлять и принимать блок независимо от того, сколько времени прошло, прежде чем я вызову sendNumbers()?

+1

Возможный дубликат [Что не так с этим кодом golang?] (Http://stackoverflow.com/questions/28958192/whats-wrong-with-this-golang-code/28958240#28958240); и [Goroutine не выполняется, если включен time.Sleep] (http://stackoverflow.com/questions/28307783/goroutine-does-not-execute-if-time-sleep-included/28307829#28307829). – icza

ответ

2

В режиме Go программа завершается, как только основная функция возвращается независимо от того, работают ли другие goroutines или нет. Если вы хотите, чтобы основная функция не выходила преждевременно, вам нужен какой-то механизм синхронизации. https://nathanleclaire.com/blog/2014/02/15/how-to-wait-for-all-goroutines-to-finish-executing-before-continuing/
Вам не обязательно использовать примитивы синхронизации, вы также можете делать это только с каналами, возможно, более идиоматичным способом сделать это.