10

If I am using channels properly, should I need to use mutexes to protect against concurrent access?

icza
  • 389,944
  • 63
  • 907
  • 827
Datsik
  • 14,453
  • 14
  • 80
  • 121

1 Answers1

12

You don't need mutex if you use channels correctly. In some cases a solution with mutex might be simpler though.

Just make sure the variable(s) holding the channel values are properly initialized before multiple goroutines try to access the channel variables. Once this is done, accessing the channels (e.g. sending values to or receiving values from them) is safe by design.

Supporting documents with references (emphases added by me):

Spec: Channel types:

A single channel may be used in send statements, receive operations, and calls to the built-in functions cap and len by any number of goroutines without further synchronization. Channels act as first-in-first-out queues. For example, if one goroutine sends values on a channel and a second goroutine receives them, the values are received in the order sent.

Effective Go: Concurrency: Share by communicating

Concurrent programming in many environments is made difficult by the subtleties required to implement correct access to shared variables. Go encourages a different approach in which shared values are passed around on channels and, in fact, never actively shared by separate threads of execution. Only one goroutine has access to the value at any given time. Data races cannot occur, by design. To encourage this way of thinking we have reduced it to a slogan:

Do not communicate by sharing memory; instead, share memory by communicating.

This approach can be taken too far. Reference counts may be best done by putting a mutex around an integer variable, for instance. But as a high-level approach, using channels to control access makes it easier to write clear, correct programs.

This article is also very helpful: The Go Memory Model

Also quoting from the package doc of sync:

Package sync provides basic synchronization primitives such as mutual exclusion locks. Other than the Once and WaitGroup types, most are intended for use by low-level library routines. Higher-level synchronization is better done via channels and communication.

Community
  • 1
  • 1
icza
  • 389,944
  • 63
  • 907
  • 827
  • 7
    While this is a great general guideline, I think we really need to stress the "This approach can be taken too far." caveat. I've seen a *lot* of horribly complicated code stem from this, with a mess of reactor loops and message passing, where a simple mutex would of sufficed. How I like to think of the problem: If you're trying to provide "mutual exclusion" around a *single* logical resource, then you probably want a mutex. If you're trying to coordinate goroutines and provide synchronization points, then you want channels. (Everything in between comes with experience) – JimB Dec 02 '15 at 14:48