美文网首页
Go 并发之读写锁

Go 并发之读写锁

作者: 三梦哥 | 来源:发表于2020-03-02 10:42 被阅读0次

    在业务当中我们常常需要遇到并发读写,其中读的频率远大于写的频率的情况,对数据的写入是需要互斥的,也就是同时只能允许一个线程去修改某个数据,但是允许多个读线程同时去读取某个数据。总的来说就是:

    • 当有一个写线程来修改某个临界量的时候,不允许其它的写线程和读线程来进入临界区;
    • 当有一个读线程来读取某个临界量的时候,不允许其它的写线程进入临界区,但允许其它的读线程来进入临界量;

    对比互斥锁和读写锁

    当使用sync.Mutex 来实现并发同步

    使用sync.Mutex来对读线程和写线程来进行互斥操作,代码如下:

    package main
    
    import (
        "fmt"
        "sync"
        "time"
    )
    
    var (
        wg   sync.WaitGroup
        lock sync.Mutex
        data int64
    )
    
    func read() {
        defer lock.Unlock()
        defer wg.Done()
        lock.Lock()
        time.Sleep(time.Millisecond) //模拟读取耗时
    }
    
    func write() {
        defer lock.Unlock()
        defer wg.Done()
        lock.Lock()
        data++
    }
    
    func main() {
        start := time.Now()
        for i := 0; i < 1000; i++ {
            wg.Add(1)
            go read()
        }
        for i := 0; i < 10; i++ {
            wg.Add(1)
            go write()
        }
        wg.Wait()
        fmt.Println(data)
        d := time.Now().Sub(start)
        fmt.Println(d)
    }
    

    结果输出如下:

    互斥锁
    容易看出,耗时1.5s

    当使用sync.RWMutex来实现并发同步

    使用sync.RWMutex来对读线程和写线程来进行互斥操作,代码如下:

    package main
    
    import (
        "fmt"
        "sync"
        "time"
    )
    
    var (
        wg   sync.WaitGroup
        lock sync.RWMutex
        data int64
    )
    
    func read() {
        defer lock.RUnlock()
        defer wg.Done()
        lock.RLock()
        time.Sleep(time.Millisecond) //模拟读取耗时
    }
    
    func write() {
        defer lock.Unlock()
        defer wg.Done()
        lock.Lock()
        data++
    }
    
    func main() {
        start := time.Now()
        for i := 0; i < 1000; i++ {
            wg.Add(1)
            go read()
        }
        for i := 0; i < 10; i++ {
            wg.Add(1)
            go write()
        }
        wg.Wait()
        fmt.Println(data)
        d := time.Now().Sub(start)
        fmt.Println(d)
    }
    

    结果输出如下:


    读写锁

    容易看出,耗时7ms

    总结

    方式 sync.Mutex sync.RWMutex
    耗时 1.5s 7ms

    所以在遇到并发读写,并且读的频率远大于写的频率的时候,需要使用sync.RWMutex读写锁来实现读写并发。

    相关文章

      网友评论

          本文标题:Go 并发之读写锁

          本文链接:https://www.haomeiwen.com/subject/caqpkhtx.html