首页 > 其他分享 >【golang】怎么在Go语言中实现锁机制

【golang】怎么在Go语言中实现锁机制

时间:2023-12-28 15:46:10浏览次数:22  
标签:... 协程 语言 读写 sync golang 互斥 Go 操作

Go语言的锁

在Go语言中,最常用的锁是互斥锁(Mutex)。互斥锁是一种特殊的二进制信号量,用于控制对共享资源的访问。Go语言通过标准库中的"sync"包提供了互斥锁的功能。互斥锁的类型定义如下:

type Mutex struct {
    state int32
    sema  uint32
}

其中state字段用于记录锁的状态,sema字段是一个信号量。

在使用互斥锁之前,需要通过调用Lock方法获取锁。如果锁已经被其他协程持有,则当前协程将会被阻塞,等待锁的释放。例如:

var mu sync.Mutex
// ...
mu.Lock()
// ...
mu.Unlock()

在这段代码中,mu是一个互斥锁。mu.Lock()用于获取锁,如果锁已经被其他协程持有,则当前协程将会被阻塞。mu.Unlock()用于释放锁。

这个机制非常简单,但实际上效率并不高。如果有很多协程试图获取同一个互斥锁,那么处理时就很容易产生拥塞,从而使得整个程序的效率降低。

读写锁

在一些需要进行读写操作的场景下,互斥锁的效率很低。因为互斥锁只能保证在同一时刻只有一个协程能够访问共享资源,读操作和写操作都需要先等待锁的释放。但是,如果只有读操作,则这种等待并没有必要。因为多个协程可以同时对同一个资源进行读操作,而不会对数据产生破坏性的修改。

这时候就需要用到读写锁(RWMutex)。读写锁是一种特殊的互斥锁。一个资源可以被多个协程同时进行读操作,但只能被一个协程进行写操作。因此,在写操作时,所有读操作将会被阻塞,等待写操作结束。读写锁的类型定义如下:

type RWMutex struct {
    w           Mutex // 用于写操作的互斥锁
    writerSem   uint32
    readerSem   uint32
    readerCount int32  // 当前进行读操作的协程数量
    readerWait  int32  // 等待读操作的协程数量
}

读写锁有两种状态:读锁和写锁。读锁状态下,多个协程可以同时进行读操作;写锁状态下,只有一个协程可以进行写操作。同时,读写锁支持协程优先级的机制,这意味着等待时间更长的协程将会首先获取到锁。

获取读锁的方法是RLock(),释放读锁的方法是RUnlock();获取写锁的方法是Lock(),释放写锁的方法是Unlock()。举个例子:

var rw sync.RWMutex
// ...
func read() {
    rw.RLock()
    // ...
    rw.RUnlock()
}
// ...
func write() {
    rw.Lock()
    // ...
    rw.Unlock()
}

这段代码演示了如何在Go语言中使用读写锁。read()函数获取了读锁,同时可以被多个协程同时调用;而write()函数获取了写锁,在同一时刻只能有一个协程调用它。

sync.Once

sync.Once是一种非常有用的锁。它只会执行一次初始化操作。Once内部有一个布尔值,如果被锁定了,那么一旦调用失败后,后续调用都将立刻返回,不会重新执行初始化。

func singleton() {
    var once sync.Once
    once.Do(func() {
        // 初始化对象
    })
    // 使用对象
}

使用sync.Once可以避免在多个协程中重复执行初始化操作。

<iframe style="display: none !important"></iframe>

标签:...,协程,语言,读写,sync,golang,互斥,Go,操作
From: https://www.cnblogs.com/cxy2020/p/17932843.html

相关文章

  • 【Golang】Golang的跳一跳
    一、基本概念在Go语言中,代码跳转是指从一个位置跳转到另一个位置。一般而言,我们可以通过函数调用进行代码跳转,也可以通过goto语句进行跳转。不同的跳转方式有不同的适用场景。二、函数调用函数是Go语言中的基本构建块之一。调用函数时,程序的执行流程会跳转到被调用的函数中,并在......
  • 【golang】Go语言实现数据转发功能
    首先,我们需要考虑数据实体的格式。在许多情况下,使用JSON格式最为方便。Go语言中有一个标准库“encoding/json”可以提供JSON编解码功能。我们可以使用它来将我们的数据序列化为JSON格式,并将其发送到目标组件中。接下来,我们需要选择一种合适的网络协议来实现数据传输。常用的协议......
  • 【golang】Go语言中interface类型怎么使用
    1、Go语言中interface类型的定义 在Go语言中,interface类型是一个抽象的类型,它是一组方法签名的集合,只要某个类型实现了这些方法,它就属于该interface类型。在Go语言中定义一个interface类型的方法,需要使用interface关键字。下面是interface类型的完整定义方式:type interfac......
  • Qt元对象语言
    1.QML(QtMeta-ObjectLanguage,Qt元对象语言)QML是一种基于CSS及JavaScript,用于描述对象间关系的声明式语言。其属性部分是CSS风格的键值对,行为部分则使用JavaScript实现。注:QML是QtMeta-ObjectLanguage,而不是QtMarkupLanguage的缩写。Image{id:root...M......
  • go-使用通道模拟抢到活动
    packagemainimport( "fmt" "gorm.io/driver/mysql" "gorm.io/gorm" "math/rand" "sync" "time")//用户结构体typeUserstruct{ Idint Namestring Telstring Addressstring}......
  • 【Django进阶】djangorestframework-jwt使用
    简介Jsonwebtoken(JWT),是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资......
  • 统一大语言模型和知识图谱:如何解决医学大模型-问诊不充分、检查不准确、诊断不完整、
    统一大语言模型和知识图谱:如何解决医学大模型问诊不充分、检查不准确、诊断不完整、治疗方案不全面?医学大模型问题如何使用知识图谱加强和补足专业能力?大模型结构知识图谱增强大模型的方法 医学大模型问题问诊。偏离主诉和没抓住核心。解决方案:建立抗干扰的能力,使得发现用户问题......
  • MongoDB Oplogs 到底都记录了什么 与 智者老冯
    最近董宇辉的事情,让我意识到,如果光一味的搞技术,那么对于人生和生活是不完整的,后序在撰写一些技术文章的时候,会带有一些对于当前热点事件的一些感触和反思,也希望能找到一些有同样想法的人,终究人生的道路是孤独的,如果在孤独中能找到一些人能对你有一些共鸣,那是一件幸福的事情。这里先......
  • 多态在不同语言间是如何实现的?
    先说结论:多态是一种思路概念。不同的语言实现方式不太一样。大致分为两种。1.接口实现 接口实现,是用于静态语言中。特点是只声明。2.继承实现。继承实现,是动态语言中。特点是,父类写个基本的,子类重写父类。就是覆盖着写,来实现。举例:java中的接口示例:interfaceA......
  • 2_C#语言基本类型
    C#语言中常见的类型预定义简单类型名称含义默认值sbyte8位有符号整数0byte8位无符号整数0short16位有符号整数0ushort16位无符号整数0int32位有符号整数0uint32位无符号整数0long64位有符号整数0ulong64为无符号整数0float(I......