2016-10-11 4 views
0

Я на примере параллелизм здесь: https://tour.golang.org/concurrency/5Что происходит в этом примере параллелизма?

Это код:

package main 

import "fmt" 

func fibonacci(c, quit chan int) { 
    x, y := 0, 1 
    for { 
     select { 
     case c <- x: 
      x, y = y, x + y 
     case <- quit: 
      fmt.Println("quit") 
      return 
     } 
    } 
} 

func main() { 
    c := make(chan int) 
    quit := make(chan int) 
    go func() { 
     for i := 0; i < 10; i++ { 
      fmt.Println(<- c) 
     } 
     quit <- 0 
    }() 
    fibonacci(c, quit) 
} 

Там довольно немного об этом, что сбивает с толку меня и тур сам по себе ничего не говорит об этом , В нем говорится, что select будет ждать операций связи, но я действительно не понимаю, как это относится к функции, которую он отправляет в goroutine перед вызовом fibonacci. fmt.Println отправляется на канал c, но я просто не понимаю, почему и как это имеет смысл ...

У меня так много вопросов об этом, я надеюсь, ...

ответ

3

В примере кода запускается goroutine и запускается до тех пор, пока он не достигнет fmt.Println(<- c), где он печатает значения, которые он получает от c. На данный момент времени i == 0 мы находимся на первой итерации. Между тем, так как это работает в горутине, main продолжает выполнение и называется fibonacci, передавая ему каналы c и quit. Функция fibonacci сидит в «бесконечном» выборе, то есть вы никогда не сможете выйти из этого без явного вызова return, как и при получении от quit канала.

Так назад в основном, где вы применит goroutine, он блокирует до получения от канала, fibonacci начинает выполнение и отправки по этому каналу, не обеспечивая следующее число в fibonacci последовательности до тех пор, завершающего цикла (когда i == 10), при которой укажите код, который перемещается вниз до quit <- 0, где отправляется на канал выхода. Поскольку вы находитесь в бесконечном выборе там в fibonacci, он всегда будет выполнять следующий доступный случай, он не может продолжить отправку по c, потому что этот канал не буферизирован, он только позволяет один элемент и заполняется, вместо этого он перемещается в случае quit потому что он получил что-то на канале quit, после чего он печатает quit и возвращается.

Надеюсь, что это поможет. Некоторые из языков могут быть не точными на 100%. На самом деле просто пытаюсь проиллюстрировать, как работает этот поток управления. Я думаю, на самом деле, выбор ждет, пока goroutine в main не сможет получить, в какой момент он переходит в оператор c <- x и отправляет. Вы можете наблюдать это, пытаясь прочитать элемент из канала после того, как все будет сделано, что вызывает панику. В сущности, они оба ждут друг друга, вы не можете отправить на полный канал, и если вы просто прочитаете его без какого-либо другого потока управления (например, выберите), вы заблокируете его, пока там что-то не получите.

+0

Спасибо за ответ, который помогает с первой частью, но теперь я запутался в инструкции select, выбирает ли она 'c <- x' часть, потому что goroutine« открывает »канал, а затем оператор switch читает что-то вроде 'if x можно отправить в c; делать ... '? Если я прав, то как я могу интерпретировать второй случай ...? – deltaskelta

+0

@ deltaskelta yep, вот основная идея. Подумайте об этом как о коммутаторе, где выполняется первое условие, которое выполняется. Вы получаете от канала 'quit', поэтому что-то, отправляющее на' quit', поместит вас в этом случае, вы отправляете 'c', поэтому что-то, прочитав' c', откроет его для другой записи, в этом случае. – evanmcdonnal

Смежные вопросы