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

 更新时间:2022年07月05日 17:29:09   作者:LiberHome  
这篇文章主要为大家介绍了Go读写锁方法示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

引言

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

这里读写锁🔐 RWMutex就应运而生了,RWMutex可以分别针对读操作和写操作进行上锁和解锁。

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

读写锁有很多方法

  • 方法一: RLock 这个方法是读锁,当写锁存在的时候,无法加载读锁,只有当不存在锁,或者只有读锁的时候才能使用。读锁可以同时加载多个,适用于多度写少的场景。
  • 方法二: 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读写锁方法的资料请关注脚本之家其它相关文章!

相关文章

  • 使用Go语言编写一个极简版的容器Container

    使用Go语言编写一个极简版的容器Container

    Docker作为一种流行的容器化技术,对于每一个程序开发者而言都具有重要性和必要性,因为容器化相关技术的普及大大简化了开发环境配置、更好的隔离性和更高的安全性,对于部署项目和团队协作而言也更加方便,本文将尝试使用Go语言编写一个极简版的容器
    2023-10-10
  • Go语言中的变量和常量

    Go语言中的变量和常量

    这篇文章介绍了Go语言中的变量和常量,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • golang日志框架之logrus的安装使用教程

    golang日志框架之logrus的安装使用教程

    logrus是一个非常强大的日志框架,具有灵活的功能和易于使用的API,适合处理各种类型的日志需求,这篇文章主要介绍了golang日志框架之logrus的安装使用,需要的朋友可以参考下
    2023-08-08
  • Go语言利用heap实现优先级队列

    Go语言利用heap实现优先级队列

    这篇文章主要为大家详细介绍了Go语言中heap的使用以及如何利用heap实现优先级队列的相关资料,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-05-05
  • 一文了解Go语言的并发特性

    一文了解Go语言的并发特性

    本文主要介绍了一文了解Go语言的并发特性,通过轻量级线程、通道及选择语句,使得并发编程变得既简单又高效,下面就来具体了解一下如何使用,感兴趣的可以了解一下
    2024-02-02
  • Go语言使用HTTP包创建WEB服务器的方法

    Go语言使用HTTP包创建WEB服务器的方法

    这篇文章主要介绍了Go语言使用HTTP包创建WEB服务器的方法,结合实例形式分析了Go语言基于HTTP包创建WEB服务器客户端与服务器端的实现方法与相关注意事项,需要的朋友可以参考下
    2016-07-07
  • Golang Gin 中间件 Next()方法示例详解

    Golang Gin 中间件 Next()方法示例详解

    这篇文章主要介绍了Golang Gin 中间件 Next()方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-04-04
  • Go Comparable Type原理深入解析

    Go Comparable Type原理深入解析

    这篇文章主要为大家介绍了Go Comparable Type原理深入解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-01-01
  • Go 语言下基于Redis分布式锁的实现方式

    Go 语言下基于Redis分布式锁的实现方式

    本篇文章将详细介绍如何正确地实现Redis分布式锁,下面通过一个项目基于 Redis 的分布式锁能够提供哪些分布锁特性,本文给大家介绍的非常详细,需要的朋友参考下吧
    2021-06-06
  • 浅析golang如何处理json中的null

    浅析golang如何处理json中的null

    json 是一种常用的数据格式,在 go 使用 json 序列化和反序列化时比较方便的,但在使用过程中,会遇到一些问题,比如 null,所以下面我们就来看看golang如何处理json中的null吧
    2023-09-09

最新评论