首页 > 其他分享 >golang锁浅谈

golang锁浅谈

时间:2023-09-05 17:14:25浏览次数:33  
标签:共享资源 浅谈 解锁 sync value golang Unlock mutex

在 Go 语言中,有以下几种常用的锁类型:

互斥锁(Mutex)

互斥锁是最常用的一种锁机制,用于保护共享资源在并发访问时的互斥操作。常见的用法如下:

var mutex sync.Mutex

// 通过 Lock() 和 Unlock() 方法保护共享资源的临界区
mutex.Lock()
// 执行对共享资源的操作
mutex.Unlock()

对于 sync.Mutex,如果在手动调用 Unlock 后,再次在 defer 中调用 Unlock,会导致 panic。这是因为 sync.Mutex 并没有内部状态来追踪锁的持有者,当重复解锁时,它会引发运行时异常。

下面是一个示例代码,演示了手动解锁后使用 defer 解锁时可能引发的异常:

package main

import (
"sync"
)

func main() {
var mutex sync.Mutex

mutex.Lock()
defer mutex.Unlock() // 在 defer 中尝试解锁

mutex.Unlock() // 手动解锁

// 此处再次调用 mutex.Unlock() 会引发 panic
}

在上述示例中,我们首先手动对互斥锁 mutex 进行解锁操作,然后在 defer 语句中尝试再次解锁。当程序执行到第二次解锁操作时,会引发 sync: unlock of unlocked mutex 的 panic 错误。

因此,在使用互斥锁时,需要确保在 defer 中不会重复解锁已经解锁的互斥锁。一种可靠的做法是只在 defer 中进行解锁操作,并避免在其他地方手动解锁。这样可以确保解锁操作的一致性,并避免不必要的错误。

读写锁(RWMutex)

读写锁允许多个读操作同时进行,但只允许一个写操作进行。常见的用法如下:

var rwLock sync.RWMutex

// 通过 RLock() 和 RUnlock() 方法保护共享资源的读操作
rwLock.RLock()
// 执行对共享资源的读操作
rwLock.RUnlock()

// 通过 Lock() 和 Unlock() 方法保护共享资源的写操作
rwLock.Lock()
// 执行对共享资源的写操作
rwLock.Unlock()

自定义锁sync.Locker

sync.Locker 是 go 标准库 sync 下定义的锁接口:

// A Locker represents an object that can be locked and unlocked.
type Locker interface {
   Lock()
   Unlock()
}

任何实现了 Lock 和 Unlock 两个方法的类,都可以作为一种锁的实现,最常见的为 go 标准库实现的 sync.Mutex.

条件变量(Cond)

条件变量用于在某个条件满足时进行阻塞和唤醒协程。常见的用法如下:

var cond sync.Cond

// 初始化条件变量
cond = sync.NewCond(&sync.Mutex{})

// 在某个条件不满足时阻塞协程
cond.L.Lock()
for !condition {
   cond.Wait()
}
// 执行对共享资源的操作
cond.L.Unlock()

// 满足条件后唤醒等待的协程
cond.Signal()
// 或者唤醒所有等待的协程
cond.Broadcast()

原子操作(Atomic)

原子操作用于在不需要互斥锁的情况下进行原子性的读取和更新操作,常见的用法如下:

var value int32

// 原子地读取 value 的值
atomic.LoadInt32(&value)

// 原子地更新 value 的值
atomic.StoreInt32(&value, newValue)

// 原子地增加 value 的值
atomic.AddInt32(&value, delta)

// 原子地比较并交换 value 的值
atomic.CompareAndSwapInt32(&value, oldValue, newValue)
 

标签:共享资源,浅谈,解锁,sync,value,golang,Unlock,mutex
From: https://www.cnblogs.com/peychou/p/17680170.html

相关文章

  • Golang匿名函数浅谈
    Go匿名函数(闭包)在Go中,匿名函数(也称为闭包)可以捕获外部变量。Go的闭包是指一个函数值(函数变量)包含了对其外部作用域中变量的引用。匿名函数可以访问和修改其外部作用域中的变量。它可以捕获外部变量的值,并在函数体中使用这些变量。下面是一个示例,展示了如何在匿名函数中捕......
  • golang接口用法浅谈
    类型接口Go不是面向对象的语言,在go里通过不同的结构体实现同一组公共接口这种组合的形式实现多态,类似C++的类和虚函数定义类型接口(InterfaceDefinition):使用type关键字定义接口,指定接口的方法签名。方法签名由方法的名称、参数列表和返回值组成,但不包含方法体。接口......
  • Golang Gorm 一对多查询 preload预加载
    预加载示例GORM允许使用 Preload通过多个SQL中来直接加载关系,例如:typeUserstruct{gorm.ModelUsernamestringOrders[]Order}typeOrderstruct{gorm.ModelUserIDuintPricefloat64}//查找user时预加载相关Orderdb.Preload("Orders").Fin......
  • 浅谈幂等设计
    1幂等性一句话,幂等就是一个执行操作,无论执行多少次,产生的效果和返回的结果都是一样的。2为什么要实现幂等性?如今随着互联网技术快速发展,业务越来越复杂,系统的高并发和关键数据的场景越来越多。在分布式系统中,机器宕机和消息丢失也是需要重点关注的问题,其中的一个典型就是幂......
  • 浅谈Mysql读写分离的坑以及应对的方案 | 京东云技术团队
    一、主从架构为什么我们要进行读写分离?个人觉得还是业务发展到一定的规模,驱动技术架构的改革,读写分离可以减轻单台服务器的压力,将读请求和写请求分流到不同的服务器,分摊单台服务的负载,提高可用性,提高读请求的性能。上面这个图是一个基础的Mysql的主从架构,1主1备3从。这种架构是客户......
  • 浅谈Mysql读写分离的坑以及应对的方案
    一、主从架构为什么我们要进行读写分离?个人觉得还是业务发展到一定的规模,驱动技术架构的改革,读写分离可以减轻单台服务器的压力,将读请求和写请求分流到不同的服务器,分摊单台服务的负载,提高可用性,提高读请求的性能。上面这个图是一个基础的Mysql的主从架构,1主1备3从。这种架构是......
  • golang编译go build -ldflags "-s -w"的 解释
    gobuild-ldflags"-s-w" 是一个Go语言的构建命令,其中使用了 -ldflags 参数来传递一些额外的链接器标志。这个命令中,-ldflags"-s-w" 传递了两个标志:-s:该标志会禁止生成可执行文件中的符号表信息,这样在执行文件时就不会暴露源代码中的函数名、变量名等符号信息。这有......
  • golang base64解码
    解码过程1.使用标准库的base64.StdEncoding.DecodeString 最开始是印象标准库有一个base64.StdEncoding.DecodeString方法可以解码,就直接使用了这个方法packagemainimport("encoding/base64""fmt")funcmain(){encrypt:="Cf1WA2nBMo3H9G2UPhlLBBVB......
  • golang realize数据库简介
    存储与数据库简介一个提供了读写,控制类接口,能够安全有效的把数据持久化的软件,就可以成为存储系统。-存储系统概览存储系统特点性能敏感既简单又复杂容易受硬件影响存储器层级结构单机存储栈RAID技术单块大容量磁盘的价格>多块小容量的磁盘单块磁盘的写入性能<多块磁盘的并发写入......
  • jetbrains GoLang设置编写proto文件的实时模板
    具体步骤1. 首先,先创建一个模板组,我这里创建为"proto"。2.下面这张图是我的模板组中的内容3.具体实时模板缩写:enum描述:enumname{}模板文字:enum$name${$END$}适用于:协议缓存区中的Other缩写:import描述:import"";模板文字:import"$file$";$END$适用......