Using Mutex lock – still deadlock

Issue

I am playing around with Goroutines and channels and wonder why I got the error in the title.
The idea is that I have one global int channel that gets incremented per routing.
By using the mutex lock I expected the channel to be locked per routine but that failed.
The code is here:

package main

import (
    "fmt"
    "sync"
)

var number = make(chan int)
var mutex = &sync.Mutex{}

func worker(wg *sync.WaitGroup, id int) {
    defer wg.Done()

    mutex.Lock()
    number <- id + <-number
    mutex.Unlock()
}

func main() {
    var wg sync.WaitGroup
    number <- 0
    for i := 0; i < 5; i++ {
        wg.Add(1)
        go worker(&wg, i)
    }

    wg.Wait()
    fmt.Println(<-number) // expected output: 0+1+2+3+4 = 10
}

https://play.golang.org/p/P5P9Bf5ZSIP

Solution

The issue here is to do with the channel you are using as it is unbuffered. An unbuffered channel will block until there is a receiver to receive the message.

Here the main go routine adds a number to the channel then creates the 5 go routines to both take off the channel and add to the channel then waits for them to complete before taking an item off the channel. Adding 0 to the channel will not take place until there is something to receive the number off it so it blocks before it even reaches the mutex.

The 5 go routines can only complete if there is something taking things off the channel.

If you change to a buffered channel by supplying a size to the make call then this starts running to completion:

package main

import (
    "fmt"
    "sync"
)

var number = make(chan int, 5)
var mutex = &sync.Mutex{}

func worker(wg *sync.WaitGroup, id int) {
    defer wg.Done()

    mutex.Lock()
    number <- id + <-number
    mutex.Unlock()
}

func main() {
    var wg sync.WaitGroup
    number <- 0
    for i := 0; i < 5; i++ {
        wg.Add(1)
        go worker(&wg, i)
    }

    wg.Wait()
    fmt.Println(<-number) // expected output: 0+1+2+3+4 = 10
}

https://play.golang.org/p/QDXuDH0RGPC

Answered By – Iain Duncan

Answer Checked By – Candace Johnson (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.