Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

what is the difference between RLock() and Lock() in Golang?

Tags:

go

mutex

what is the difference between RLock() and Lock() in Golang and how they can be used efficiently when we use mutex Lock ?

like image 448
Sharath BJ Avatar asked Nov 22 '18 09:11

Sharath BJ


People also ask

How do locks work in Golang?

Any code present between a call to Lock and Unlock will be executed by only one Goroutine. If one Goroutine already has the lock and if a new Goroutine is trying to get the lock, then the new Goroutine will be stopped until the mutex is unlocked.

What are mutexes 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. There are two methods defined on Mutex namely Lock and Unlock.

What is sync Mutex lock?

A Mutex guarantees only that if something has locked it, it cannot be locked again by something else until the lock is first released. It is up to you to use it correctly, by ensuring that you obtain a lock before you try to access whatever you want protected by the lock, as you've done in your example main .


1 Answers

Lock(): only one go routine read/write at a time by acquiring the lock.

RLock(): multiple go routine can read(not write) at a time by acquiring the lock.

package main

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

func main() {

    a := 0

    lock := sync.RWMutex{}

    for i := 1; i < 10; i++ {
        go func(i int) {
            lock.Lock()
            fmt.Printf("Lock: from go routine %d: a = %d\n",i, a)
            time.Sleep(time.Second)
            lock.Unlock()
        }(i)
    }

    b := 0

    for i := 11; i < 20; i++ {
        go func(i int) {
            lock.RLock()
            fmt.Printf("RLock: from go routine %d: b = %d\n",i, b)
            time.Sleep(time.Second)
            lock.RUnlock()
        }(i)
    }

    <-time.After(time.Second*10)
}

1) When a go-routine has already acquired a RLock(), can another go-routine acquire a Lock() for write or it has to wait until RUnlock() happens?

  • To acquire a Lock() for write it has to wait until RUnlock()

2) What happens when someone already acquired Lock() for map ,will other go-routine can still get RLock()

  • if someone X already acquired Lock(), then other go-routine to get RLock() will have to wait until X release lock (Unlock())

3) Assuming we are dealing with Maps here, is there any possibility of "concurrent read/write of Map" error can come?

  • Map is not thread safe. so "concurrent read/write of Map" can cause error.

See following example for more clarification:

package main

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

func main() {
    lock := sync.RWMutex{}

    b := map[string]int{}
    b["0"] = 0

    go func(i int) {
        lock.RLock()
        fmt.Printf("RLock: from go routine %d: b = %d\n",i, b["0"])
        time.Sleep(time.Second*3)
        fmt.Printf("RLock: from go routine %d: lock released\n",i)
        lock.RUnlock()
    }(1)

    go func(i int) {
        lock.Lock()
        b["2"] = i
        fmt.Printf("Lock: from go routine %d: b = %d\n",i, b["2"])
        time.Sleep(time.Second*3)
        fmt.Printf("Lock: from go routine %d: lock released\n",i)
        lock.Unlock()
    }(2)

    <-time.After(time.Second*8)

    fmt.Println("*************************************8")

    go func(i int) {
        lock.Lock()
        b["3"] = i
        fmt.Printf("Lock: from go routine %d: b = %d\n",i, b["3"])
        time.Sleep(time.Second*3)
        fmt.Printf("Lock: from go routine %d: lock released\n",i)
        lock.Unlock()
    }(3)

    go func(i int) {
        lock.RLock()
        fmt.Printf("RLock: from go routine %d: b = %d\n",i, b["3"])
        time.Sleep(time.Second*3)
        fmt.Printf("RLock: from go routine %d: lock released\n",i)
        lock.RUnlock()
    }(4)

    <-time.After(time.Second*8)
}
like image 153
nightfury1204 Avatar answered Sep 29 '22 00:09

nightfury1204