go mutex

The Go programming language provides a built-in package called sync that allows us to implement mutual exclusion using a mutex. A mutex, short for mutual exclusion, is a synchronization primitive that ensures that only one thread or goroutine can access a shared resource at a time. In Go, a mutex is implemented using the sync.Mutex type.

Step 1: Import the sync package

To use the mutex in Go, we first need to import the sync package. This can be done using the import statement:

import "sync"

Step 2: Create a Mutex object

Next, we need to create a mutex object using the sync.Mutex type. This mutex object will be used to control access to the shared resource. We can create a mutex object by declaring a variable of type sync.Mutex.

var mutex sync.Mutex

Step 3: Lock the Mutex

Before accessing the shared resource, we need to acquire a lock on the mutex. This can be done by calling the Lock() method on the mutex object. If the mutex is already locked by another goroutine, the Lock() method will block until the mutex becomes available.

mutex.Lock()

Step 4: Access the Shared Resource

Once we have acquired the lock on the mutex, we can safely access the shared resource. This is the critical section of code where we perform operations on the shared resource.

// Perform operations on the shared resource

Step 5: Unlock the Mutex

After we have finished accessing the shared resource, we need to release the lock on the mutex to allow other goroutines to access the shared resource. This can be done by calling the Unlock() method on the mutex object.

mutex.Unlock()

By unlocking the mutex, we signal that we are done with the critical section of code and other goroutines can now acquire the lock and access the shared resource.

This sequence of steps ensures that only one goroutine can access the shared resource at a time, preventing data races and ensuring that the shared resource is accessed safely.

Here is a complete example that demonstrates the usage of a mutex in Go:

package main

import (
    "fmt"
    "sync"
)

var (
    counter int
    mutex   sync.Mutex
    wg      sync.WaitGroup
)

func main() {
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go increment()
    }
    wg.Wait()
    fmt.Println("Counter:", counter)
}

func increment() {
    defer wg.Done()

    mutex.Lock()
    counter++
    mutex.Unlock()
}

In this example, we have a shared counter variable that is incremented by multiple goroutines. The increment function is called concurrently by multiple goroutines, and each goroutine acquires a lock on the mutex before incrementing the counter. By using the mutex, we ensure that the counter is incremented safely without any data races.

I hope this explanation helps! Let me know if you have any further questions.