2014-01-11 6 views
8

Может кто-нибудь объяснить, почему, если канал буферизирован, программа не выходит с fatal_error?Буферизованный/небуферизованный канал

Unbuffered канал

package main 

func main() { 
    c := make(chan int) 
    c <- 3 
} 

fatal error: all goroutines are asleep - deadlock! 

буферизацией канал

package main 

func main() { 
    c := make(chan int, 1) 
    c <- 3 
} 

[no output] 

Program exited. 

Спасибо!

+0

Я думаю, это потому, что разница между буферизованными и небуферизованными каналами. В буферизованных каналах отправитель ожидает, пока получатель (сам в этом случае) получит данные. Но я не уверен. –

+2

Возможный дубликат [Как сделать (chan bool) вести себя иначе, чем make (chan bool, 1)?] (Http://stackoverflow.com/questions/20041392/how-does-makechan -bool-себя-разному: от-makechan-BOOL-1) – Matt

ответ

11

Запись в буферный канал не блокируется, если в буфере есть место.

Если вы пытаетесь поставить два элемента в канале с размером буфера одного, вы получите ту же ошибку:

package main 

func main() { 
    c := make(chan int, 1) 
    c <- 3 
    c <- 4 
} 

дает вам:

fatal error: all goroutines are asleep - deadlock! 
2

Это основная концепция каналов Go (или других версий CSP, таких как библиотека core.async Clojure), которые они блокируют. В общем, как уже упоминалось, там уже два типа каналов:

  • буферном, которые блокируют, если буфер заполнен.
  • небуферизован, какой блок, если нет «Рандеву», то есть должен быть кто-то, кто ставит (c <-), чтобы и тот, кто принимает (<- c) из канала.

В вашем конкретном случае выполнения Go достаточно умны, чтобы обнаружить, что нет ни одного человека, который будет когда-нибудь 3 из канала c. Следовательно, это deadlock и (к счастью) ошибка.

Что вы обычно делаете, когда вы работаете с каналами используются goroutines (проверка this introduction), который нерест легкого поточно-управляемый Go во время выполнения, чтобы выполнить тело по совместительству:

c := make(chan int) 

go func() { c <- 3 }() // Create a new gorountine that puts 3 to the channel 

fmt.Println(<- c) // Take 3 from the channel and print it in the main thread 
Смежные вопросы