Se sto usando i canali correttamente dovrei usare i mutex?

Se sto usando i canali correttamente, dovrei usare i mutex per proteggermi da accessi concorrenti?

Non hai bisogno di mutex se usi i canali correttamente. In alcuni casi, tuttavia, una soluzione con mutex potrebbe essere più semplice.

Assicurati solo che le variabili che contengono i valori dei canali siano inizializzate correttamente prima che più goroutine provino ad accedere alle variabili di canale. Una volta eseguita questa operazione, l’accesso ai canali (ad esempio l’invio di valori o la ricezione di valori da essi) è sicuro in base alla progettazione.

Documenti di supporto con riferimenti (sottolineati da me):

Spec: tipi di canali:

Un singolo canale può essere utilizzato nelle istruzioni di invio , nelle operazioni di ricezione e nelle chiamate alle funzioni integrate cap e len da un numero qualsiasi di goroutine senza ulteriore sincronizzazione . I canali agiscono come code first-in-first-out. Ad esempio, se una goroutine invia valori su un canale e una seconda goroutine li riceve, i valori vengono ricevuti nell’ordine inviato.

Go efficace: concorrenza: condividi comunicando

La programmazione concorrente in molti ambienti è resa difficile dalle sottigliezze necessarie per implementare l’accesso corretto alle variabili condivise. Go incoraggia un approccio diverso in cui i valori condivisi vengono trasmessi sui canali e, di fatto, non vengono mai condivisi triggersmente da thread di esecuzione separati. Solo una goroutine ha accesso al valore in qualsiasi momento. Le gare di dati non possono verificarsi, in base alla progettazione. Per incoraggiare questo modo di pensare lo abbiamo ridotto a uno slogan:

Non comunicare condividendo la memoria; invece, condividi la memoria comunicando.

Questo approccio può essere preso troppo lontano. I conteggi di riferimento possono essere fatti meglio inserendo un mutex attorno a una variabile intera, per esempio. Ma come approccio di alto livello, l’uso dei canali per controllare l’accesso facilita la scrittura di programmi chiari e corretti.

Questo articolo è anche molto utile: il modello Go Memory

Citando anche dal pacchetto doc di sync :

La sincronizzazione dei pacchetti fornisce le primitive di sincronizzazione di base come i blocchi di esclusione reciproca. Oltre ai tipi Once e WaitGroup, la maggior parte sono destinati all’uso da routine di libreria di basso livello. La sincronizzazione di livello superiore viene eseguita meglio tramite canali e comunicazioni.