Andrew Gerrand | 5bc444d | 2014-12-10 11:35:11 +1100 | [diff] [blame] | 1 | # Use a sync.Mutex or a channel? |
| 2 | |
| 3 | One of Go's mottos is _"Share memory by communicating, don't communicate by sharing memory."_ |
| 4 | |
| 5 | That said, Go does provide traditional locking mechanisms in the <a href='http://golang.org/pkg/sync/'>sync package</a>. Most locking issues can be solved using either channels or traditional locks. |
| 6 | |
| 7 | So which should you use? |
| 8 | |
| 9 | Use whichever is most expressive and/or most simple. |
| 10 | |
| 11 | A common Go newbie mistake is to over-use channels and goroutines just because it's possible, and/or because it's fun. Don't be afraid to use a <a href='http://golang.org/pkg/sync/#Mutex'><code>sync.Mutex</code></a> if that fits your problem best. Go is pragmatic in letting you use the tools that solve your problem best and not forcing you into one style of code. |
| 12 | |
| 13 | As a general guide, though: |
| 14 | |
Rick Beton | 901b5a6 | 2015-03-19 14:52:22 +0000 | [diff] [blame] | 15 | | **Channel** | **Mutex** | |
| 16 | |:------------|:----------| |
Andrew Gerrand | 5bc444d | 2014-12-10 11:35:11 +1100 | [diff] [blame] | 17 | | passing ownership of data,<br />distributing units of work,<br /> communicating async results | caches,<br />state | |
| 18 | |
| 19 | If you ever find your sync.Mutex locking rules are getting too complex, ask yourself whether using channel(s) might be simpler. |
| 20 | |
Rick Beton | d59028d | 2015-03-19 15:50:34 +0000 | [diff] [blame] | 21 | ### Wait Group |
Rick Beton | 901b5a6 | 2015-03-19 14:52:22 +0000 | [diff] [blame] | 22 | |
Rick Beton | d59028d | 2015-03-19 15:50:34 +0000 | [diff] [blame] | 23 | Another important synchronisation primitive is sync.WaitGroup. These allow co-operating goroutines to collectively wait for a threshold event before proceeding independently again. This is useful typically in two cases. |
Rick Beton | 901b5a6 | 2015-03-19 14:52:22 +0000 | [diff] [blame] | 24 | |
Rick Beton | b538d91 | 2015-03-19 14:55:13 +0000 | [diff] [blame] | 25 | Firstly, when 'cleaning up', a sync.WaitGroup can be used to ensure that all goroutines - including the main one - wait before all terminating cleanly. |
| 26 | |
| 27 | The second more general case is of a cyclic algorithm that involves a set of goroutines that all work independently for a while, then all wait on a barrier, before proceeding independently again. This pattern might be repeated many times. Data might be exchanged at the barrier event. This strategy is the basis of [Bulk Synchronous Parallelism](https://en.wikipedia.org/wiki/Bulk_synchronous_parallel) (BSP). |
Rick Beton | 901b5a6 | 2015-03-19 14:52:22 +0000 | [diff] [blame] | 28 | |
Rick Beton | d59028d | 2015-03-19 15:50:34 +0000 | [diff] [blame] | 29 | Channel communication, mutexes and wait-groups are complementary and can be combined. |
| 30 | |
| 31 | ### More Info |
Andrew Gerrand | 5bc444d | 2014-12-10 11:35:11 +1100 | [diff] [blame] | 32 | |
| 33 | * Channels in Effective Go: http://golang.org/doc/effective_go.html#channels |
Rick Beton | 901b5a6 | 2015-03-19 14:52:22 +0000 | [diff] [blame] | 34 | * The sync package: http://golang.org/pkg/sync/ |