dongyun4010
dongyun4010
2018-11-22 09:36
浏览 961
已采纳

Golang中的RLock()和Lock()有什么区别?

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

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

2条回答 默认 最新

  • dopcpc9207
    dopcpc9207 2018-11-22 10:50
    已采纳

    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
    ",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
    ",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
    ",i, b["0"])
            time.Sleep(time.Second*3)
            fmt.Printf("RLock: from go routine %d: lock released
    ",i)
            lock.RUnlock()
        }(1)
    
        go func(i int) {
            lock.Lock()
            b["2"] = i
            fmt.Printf("Lock: from go routine %d: b = %d
    ",i, b["2"])
            time.Sleep(time.Second*3)
            fmt.Printf("Lock: from go routine %d: lock released
    ",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
    ",i, b["3"])
            time.Sleep(time.Second*3)
            fmt.Printf("Lock: from go routine %d: lock released
    ",i)
            lock.Unlock()
        }(3)
    
        go func(i int) {
            lock.RLock()
            fmt.Printf("RLock: from go routine %d: b = %d
    ",i, b["3"])
            time.Sleep(time.Second*3)
            fmt.Printf("RLock: from go routine %d: lock released
    ",i)
            lock.RUnlock()
        }(4)
    
        <-time.After(time.Second*8)
    }
    
    点赞 评论
  • douji1077
    douji1077 2018-11-22 09:50

    A RWMutex is a reader/writer mutual exclusion lock. The lock can be held by an arbitrary number of readers or a single writer. The zero value for a RWMutex is an unlocked mutex.

    A RWMutex must not be copied after first use.

    If a goroutine holds a RWMutex for reading and another goroutine might call Lock, no goroutine should expect to be able to acquire a read lock until the initial read lock is released. In particular, this prohibits recursive read locking. This is to ensure that the lock eventually becomes available; a blocked Lock call excludes new readers from acquiring the lock.


    A Mutex is a mutual exclusion lock. The zero value for a Mutex is an unlocked mutex.

    The golang provide the channel is the best practice for concurrency control, so i think the efficiently way using sync.lock is not used it, use channel instead.

    点赞 评论

相关推荐