Sincronizzazione

Quando si hanno più routines concorrenti e in comunicazione tra loro, sorge subito il problema della sincronizzazione delle operazioni.

Il programma emula una goroutine che lavora per cinque secondi, poi comunica la sua terminazione al main col channel done.
Il main è bloccato finchè non riceve tale notifica dalla goroutine.

Questo è uno schema molto comune.

Esempio

(250channel-synchronization.go):

package main

import "fmt"
import "time"

// I channel si usano per sincronizzare le goroutine
// Funzione da eseguire in una goroutine
// done è il channel di sincronizzazione
func worker(done chan bool) {
	fmt.Print("working...")
	// Attende 5 secondi
	time.Sleep(5*time.Second)
	fmt.Println("done")
	// Notifica della fine del lavoro
	done <- true
}

func main() {

	// Creazione del channel bufferizzato
	done := make(chan bool, 1)
	// E' invocata la goroutine
	fmt.Println("Blocking in main")
	go worker(done)
	// Si blocca fino alla ricezione del messaggio
	<-done
	fmt.Println("Unblocked main")
}

In questo paericolare caso, se anzichè un channel bufferizzato di un elemento si fosse usato un channel normale, il funzionamento sarebbe stato lo stesso:

done := make(chan bool)