Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does Rob Pike mean by "the synchronization nature of the channels" in Go?

Tags:

go

Here is a code example taken from "Google I/O 2012 - Go Concurrency Patterns" (slides)

package main

import (
    "fmt"
    "time"
)

func main() {
    joe := boring("Joe")
    ann := boring("Ann")
    for i := 0; i < 5; i++ {
        fmt.Println(<-joe)
        fmt.Println(<-ann)
    }
    fmt.Println("The end")
}

func boring(msg string) <-chan string {
    c := make(chan string)
    go func() {
        for i := 0; ; i++ {
            c <- fmt.Sprintf("%s %d", msg, i)
            time.Sleep(time.Second)
        }
    }()
    return c
}

The output:

Joe 0
Ann 0
Joe 1
Ann 1
Joe 2
Ann 2
Joe 3
Ann 3
Joe 4
Ann 4
The end

This is the explanation by Rob Pike, the speaker (16:33 in the video): "...we're reading a value from Joe and a value from Ann. And because of the synchronization nature of the channels, the two guys are taking turns, not only in printing the values out, but also in executing them. Because if Ann is ready to send a value but Joe hasn't done that yet, Ann will still be blocked, waiting to deliver the value to main."

This confused me. What's the meaning of "if Ann is ready to send a value but Joe hasn't done that yet, Ann will still be blocked"? As we know, a channel builds the communication between two goroutines and synchronizes their executions. But we have crated two channels here (joe and ann). The main goroutine talks with two new goroutines via joe and ann, respectively. Does that mean the synchronization nature is also valid between channels? Or that the main goroutine can talk with only one other goroutine at a time?

like image 518
Pauli Avatar asked Dec 19 '22 00:12

Pauli


1 Answers

It just means those channels are unbuffered.

    fmt.Println(<-joe)
    fmt.Println(<-ann)

The second line won't be able to execute before the first completes.
And the first won't complete until something writes in joe's channel.

Ann won't be able to write in Ann's channel if that channel has already a value.
And that channel won't be read (fmt.Println(<-ann)) until joe's channel is read first (fmt.Println(<-joe)).

Both channels are independent (unaware of each other), but the sequential nature of the read operations make one waiting for the other to be read first.

like image 99
VonC Avatar answered Apr 05 '23 23:04

VonC