Go读写锁操作方法示例详解

2022-07-05 19:47:01
目录
引言读写锁有很多方法读操作写操作

引言

前面讲到,在资源竞争的时候可以使用互斥锁,保证了资源访问的唯一性,但也降低了性能,仔细分析一下场景,如果只是读取数据,无论多少个goroutine都是不会存在逻辑上的互斥操作的。

这里读写锁????>

RWMutex同一时刻允许多个读操作进行,但只允许一个写操作进行,同时,在某一个写操作进行的时候,读操作不可进行。

读写锁有很多方法

    方法一:>方法二: RUnlock 这个方法是读解锁,用来撤销单次的读锁操作。方法三: Lock 这个方法是写上锁,如果在添加写上锁之前已经有其他的读锁和写锁了,此时,这个Lock会被阻塞,直到可以使用。方法四: Unlock 这个方法是写解锁,如果没有绑定写锁就直接写解锁,会引发运行时错误。

    读操作

    下面用实际的代码做例子,看一下读操作:

    package main
    import (
        "fmt"
        "sync"
        "time"
    )
    //新建一个锁对象的指针,然后待会儿再指针中创建这个锁的对象
    var rwMutex *sync.RWMutex
    //为了保证 子的goroutine先执行,可以使用同步等待组wg,这里创建wg的指针类型
    var wg *sync.WaitGroup
    func main() {
        rwMutex = new(sync.RWMutex)
        wg = new(sync.WaitGroup)
        wg.Add(2)//这里记得+add
        //    在主函数中 启动2条goroutine
        go readData(1)
        go readData(2)
        wg.Wait()
        fmt.Println("main func end")
    }
    func readData(i int) {
        defer wg.Done()
        fmt.Println(i, "start locking!")
        //    给读操作 上锁
        rwMutex.RLock()
        //    读数据
        fmt.Println(i, "Reading data")
        //  睡一下
        time.Sleep(1 * time.Second)
        //    读解锁
        rwMutex.RUnlock()
        //打印提示信息
        fmt.Println(i, "Read over")
    }

    代码运行结果如下:

    2 start locking!
    2 Reading data
    1 start locking!
    1 Reading data
    2 Read over
    1 Read over
    main func end

    从打印结果可知,第二条goroutine先上读锁,然后第二条开始读取,然后第一条上读锁【从这里就可以看出,因为第二条的读锁还没读解锁,第一条的读锁就上了,所以这里的读锁并不互斥】,之后第一条开始读取,第二条读解锁,第一条读解锁。主goroutine结束。

    写操作

    package main
    import (
        "fmt"
        "sync"
        "time"
    )
    //新建一个锁对象的指针,然后待会儿再指针中创建这个锁的对象
    var rwMutex *sync.RWMutex
    //为了保证 子的goroutine先执行,可以使用同步等待组wg,这里创建wg的指针类型
    var wg *sync.WaitGroup
    func main() {
        rwMutex = new(sync.RWMutex)
        wg = new(sync.WaitGroup)
        wg.Add(4)
        //    在主函数中 启动2条goroutine
        go readData(1)
        go readData(2)
        go writeData(3)
        go writeData(4)
        wg.Wait()
        fmt.Println("main func end")
    }
    func readData(i int) {
        defer wg.Done()
        fmt.Println(i, "start locking!")
        //    给读操作 上锁
        rwMutex.RLock()
        //    读数据
        fmt.Println(i, "Reading data")
        //  睡一下
        time.Sleep(1 * time.Second)
        //    读解锁
        rwMutex.RUnlock()
        //打印提示信息
        fmt.Println(i, "Read over")
    }
    func writeData(i int) {
        defer wg.Done()
        fmt.Println(i, " Writing Start")
        //写上锁
        rwMutex.Lock()
        fmt.Println(i, "~~~ writing right now~~~")
        time.Sleep(1 * time.Second)
        rwMutex.Unlock()
        fmt.Println(i, "writing completed")
    }

    代码运行结果如下:

    2 start locking!
    2 Reading data
    4  Writing Start
    1 start locking!
    3  Writing Start
    2 Read over
    4 ~~~ writing right now~~~
    4 writing completed
    1 Reading data
    1 Read over
    3 ~~~ writing right now~~~
    3 writing completed
    main func end

    分析可知,只有在goroutine4结束写之后goroutine3才拿到权限开始写。

    不过讲真,到处都是lock 和 unlock,临界区什么的,真的是臃肿又容易出问题。
    go语言中多个协程想共享数据的时候,将会有更加优雅的处理方式。

    以上就是Go读写锁方法示例详解的详细内容,更多关于Go读写锁方法的资料请关注易采站长站其它相关文章!