Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can we use channels in Go in place of mutex?

Tags:

Channels combine communication—the exchange of a value—with synchronization—guaranteeing that two calculations (goroutines) are in a known state.

How is it possible to use the channels in Google Go to perform the functionality of mutex?

package main

import "sync"

var global int = 0
var m sync.Mutex

func thread1(){
    m.Lock()
    global = 1
    m.Unlock()
}

func thread2(){
    m.Lock()
    global = 2
    m.Unlock()
}

func main(){
   go thread1()
   go thread2()
}
like image 911
Kevin Avatar asked Oct 17 '10 04:10

Kevin


People also ask

How are channels implemented in Go?

In Go, when a goroutine tries to send data to a full channel, it is added to a queue in the channel struct. This causes the goroutine to block. As space becomes available on the buffer, the Go runtime will pop the first goroutine off the queue and add the data to the buffer. Thus, unblocking the goroutine.

What is the use of channel in Golang?

So, what are the channels in Golang exactly? Channels are the medium through which goroutines can communicate with each other. In simple terms, a channel is a pipe that allows a goroutine to either put or read the data.

Why do we need mutex in Golang?

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. Mutex is available in the sync package.

Is Golang a FIFO channel?

Buffered channels in Go are always FIFO. The specification clearly says: Channels act as first-in-first-out queues. If the values coming out of the channel are not FIFO, then this is a bug in the channel implementation.


2 Answers

An example of using a Channel as a Mutex:

package main

var global int = 0
var c = make(chan int, 1)

func thread1(){
    <-c // Grab the ticket
    global = 1
    c <- 1 // Give it back
}

func thread2(){
    <-c
    global = 2
    c <- 1
}

func main() {
   c <- 1 // Put the initial value into the channel
   go thread1()
   go thread2()
}

You could also use chan struct{} instead of chan int to reduce the memory size. The value that goes into it is struct{}{} (type struct{} and an empty content {}). See Ivan black's comment for an example.

like image 104
Markus Jarderot Avatar answered Oct 22 '22 01:10

Markus Jarderot


If you have a channel c that you initialize with 1 item in it, then you can "check out" the "mutex" by removing the value from the channel (<-c). You can "release" it by adding the value back (c <- 1).

Since the extract-from-channel operator a) is atomic, and b) blocks until there's something to extract, it works as a mutex, since if one thread of execution already has it checked out, there will be nothing in the channel, and thus it will block until the thread that had it checked out returns a value to the channel for another thread to extract.

like image 25
Amber Avatar answered Oct 22 '22 01:10

Amber