Когда канал блокирует программу - PullRequest
0 голосов
/ 21 июня 2019

Если я определяю канал без буфера и записываю в него одни данные, немедленно ли он блокируется (так что ядро ​​будет искать другую разблокированную программу, которая читает из канала), или он продолжает выполнение и блокирует, когда в следующий разкакой-то код пытается снова записать в канал, когда он еще не прочитан?

Ниже приведены два кода, которые я написал для исследования этой проблемы.

code1:

package main

import "fmt"

func main() {
    c := make(chan int)
    go func() {
        for i := 0;i < 3; i++ {
            c <- i
            fmt.Printf("number %v inserted into channel\n", i)
        }
    }()
    for i := 0; i < 3; i++ {
        fmt.Printf("number poped from channel %v\n", <-c)
    }
}

Вывод выглядит следующим образом:

number 0 inserted into channel
number poped from channel 0
number poped from channel 1
number 1 inserted into channel
number 2 inserted into channel
number poped from channel 2

После того, как в первый раз записывается c, эта процедура, похоже, продолжает выполняться, поскольку было напечатано «число 0, вставленное в канал».

code2:

package main

import "fmt"

func main() {
    c := make(chan int)
    c <- 2
    fmt.Println("Something is written into channel")
    <-c
}

Этот фрагмент кода не может работать правильно, так как во время выполнения сообщается об ошибке взаимоблокировки.

fatal error: all goroutines are asleep - deadlock!

На мой взгляд, когда c <-2 выполняется, процедура заблокирована (если она не заблокирована, будет выполнена строка fmt.Println, и продолжение выполнения разблокирует c при <-c).Когда эта подпрограмма заблокирована, ядро ​​ищет другие подпрограммы и не находит ни одной, поэтому сообщает об ошибке взаимоблокировки. </p>

Итак, в первом фрагменте кода я заключаю, что запись в канал не блокирует выполнение подпрограммы.немедленно, но из второго куска кода это делает.Где я ошибся и когда канал блокирует выполнение программы?

1 Ответ

5 голосов
/ 21 июня 2019

Отправка на канал без свободного буферного пространства блокирует отправителя, пока отправка не может быть завершена;Прием из канала без доступных сообщений блокирует приемник до тех пор, пока прием не может завершиться.Небуферизованный канал никогда не имеет буферного пространства - отправляет блок до тех пор, пока что-то не получит, и наоборот.Это описано в статье «Тур по Го»: https://tour.golang.org/concurrency/2

Помните, что ваш код работает одновременно, поэтому вы не можете слишком много читать в порядке выходных операторов.Goroutine может быть помещен в режим ожидания между операцией отправки / получения и когда ваше сообщение распечатывается на стандартный вывод.

...