Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When should you use a mutex over a channel?

Tags:

concurrency

go

For the past few weeks I've been wrestling with one (not-so) simple question:

When is it best to use a sync.Mutex and, conversely, when is it best use a chan?

It seems that for a lot of problems either strategy is interchangeable with the other - and that's just the problem!

Take this video found in the Golang documentation. Below, I've taken the liberty to dictate the code in the playground and also translate it to a sync.Mutex equivalent.

Is there a certain problem - encountered in the real world - that warrants the use of one other?

Notes:

  • I am a huge fan of this use of chan and struggle to think of a more elegant implementation using sync.Mutex.
  • It's worth noting that the chan implementation does more work in the same time (reaches 12)*

Playgrounds:

  • Chan implementation
  • Mutex implementation

Ping/pong with chan:

package main

import (
    "fmt"
    "time"
)

type Ball struct { hits int }

func main() {
    table := make(chan *Ball)
    go player("ping", table)
    go player("pong", table)

    table <- new(Ball)
    time.Sleep(1 * time.Second)
    <-table
}

func player(name string, table chan *Ball) {
    for {
        ball := <-table
        ball.hits++
        fmt.Println(name, ball.hits)
        time.Sleep(100 * time.Millisecond)
        table <- ball
    }
}

Ping/pong with sync.Mutex:

package main

import (
    "fmt"
    "time"
    "sync"
)

type Ball struct { hits int }

var m =  sync.Mutex{}

func main() {
    ball := new(Ball)
    go player("ping", ball)
    go player("pong", ball)

    time.Sleep(1 * time.Second)
}

func player(name string, ball *Ball) {
    for {
        m.Lock()
        ball.hits++
        fmt.Println(name, ball.hits)
        time.Sleep(100 * time.Millisecond)
        m.Unlock()

    }
}
like image 533
muiiu Avatar asked Nov 15 '17 16:11

muiiu


People also ask

Why use Mutex in Go?

A Mutex is used to provide a locking mechanism to ensure that only one Goroutine is running the critical section of code at any point in time to prevent race conditions from happening.

Are channels thread-safe Golang?

For anyone who isn't familiar with Go, channels are a mechanism that allow goroutines (which are similar to threads) to pass data from one to another. That makes it easier to write thread-safe concurrent programs and prevent race conditions.

How do you stop locks in Golang?

Common solutions are to use sync. Mutex , sync. RWMutex , or a mutex implemented with chan . Depending on how your application is structured, we can avoid locking with select .

What is select Golang?

The select statement lets a goroutine wait on multiple communication operations. A select blocks until one of its cases can run, then it executes that case. It chooses one at random if multiple are ready.


1 Answers

In Go, channels are fantastic, and you can use them to communicate between goroutines. However, you may want to use the sync.Mutex in some circumstances for convenience. These circumstances are like the following:

  • Guarding an internal state
  • Cache problems
  • For better performance

Here are three examples and explanations

  1. A simple counter

enter image description here

  1. Ping Pong Game

enter image description here

  1. The Simplest Cache

enter image description here

like image 128
Jerry An Avatar answered Oct 01 '22 20:10

Jerry An