Go 互斥锁的实现原理?

Go sync包提供了两种锁类型:互斥锁sync.Mutex 和 读写互斥锁sync.RWMutex,都属于悲观锁。

概念

Mutex是互斥锁,当一个 goroutine 获得了锁后,其他 goroutine 不能获取锁(只能存在一个写者或读者,不能同时读和写)

使用场景

多个线程同时访问临界区,为保证数据的安全,锁住一些共享资源, 以防止并发访问这些共享数据时可能导致的数据不一致问题。

获取锁的线程可以正常访问临界区,未获取到锁的线程等待锁释放后可以尝试获取锁

底层实现结构

互斥锁对应的是底层结构是sync.Mutex结构体,,位于 src/sync/mutex.go中

type Mutex struct {  state int32  sema  uint32}

state表示锁的状态,有锁定、被唤醒、饥饿模式等,并且是用state的二进制位来标识的,不同模式下会有不同的处理方式

mutex_state

sema表示信号量,mutex阻塞队列的定位是通过这个变量来实现的,从而实现goroutine的阻塞和唤醒

mutex_sema

addr = &sema
func semroot(addr *uint32) *semaRoot {  return &semtable[(uintptr(unsafe.Pointer(addr))>>3)%semTabSize].root  
}
root := semroot(addr)
root.queue(addr, s, lifo)
root.dequeue(addr)var semtable [251]struct {  root semaRoot  ...
}type semaRoot struct {  lock  mutex  treap *sudog // root of balanced tree of unique waiters.  nwait uint32 // Number of waiters. Read w/o the lock.  
}type sudog struct {g *g  next *sudog  prev *sudogelem unsafe.Pointer // 指向sema变量waitlink *sudog // g.waiting list or semaRoot  waittail *sudog // semaRoot...
}

操作

锁的实现一般会依赖于原子操作、信号量,通过atomic 包中的一些原子操作来实现锁的锁定,通过信号量来实现线程的阻塞与唤醒

加锁

通过原子操作cas加锁,如果加锁不成功,根据不同的场景选择自旋重试加锁或者阻塞等待被唤醒后加锁

func (m *Mutex) Lock() {// Fast path: 幸运之路,一下就获取到了锁if atomic.CompareAndSwapInt32(&m.state, 0, mutexLocked) {return}// Slow path:缓慢之路,尝试自旋或阻塞获取锁m.lockSlow()
}

解锁

通过原子操作add解锁,如果仍有goroutine在等待,唤醒等待的goroutine

mutex_unlock

func (m *Mutex) Unlock() {  // Fast path: 幸运之路,解锁new := atomic.AddInt32(&m.state, -mutexLocked)  if new != 0 {  // Slow path:如果有等待的goroutine,唤醒等待的goroutinem.unlockSlow()}  
}

注意点:

  • 在 Lock() 之前使用 Unlock() 会导致 panic 异常
  • 使用 Lock() 加锁后,再次 Lock() 会导致死锁(不支持重入),需Unlock()解锁后才能再加锁
  • 锁定状态与 goroutine 没有关联,一个 goroutine 可以 Lock,另一个 goroutine 可以 Unlock

本文节选于Go合集《Go语言面试题精讲》
GOLANG ROADMAP 一个专注Go语言学习、求职的社区。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/267626.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据抽取平台pydatax介绍--实现和项目使用

数据抽取平台pydatax实现过程中,有2个关键点: 1、是否能在python3中调用执行datax任务,自己测试了一下可以,代码如下: 这个str1就是配置的shell文件 try:result os.popen(str1).read() except Exception as …

Vue2:用node+express部署Vue项目

一、编译项目 命令 npm run build执行命令后,我们会在项目文件夹中看到如下生成的文件 二、部署Vue项目 接上一篇,nodeexpress编写轻量级服务 1、在demo中创建static文件夹 2、将dist目录中的文件放入static中 3、修改server.js文件 关键配置&…

【EAI 026】RoboGen: 通过自动数据生成管线实现机器人技能学习

Paper Card 论文标题:RoboGen: Towards Unleashing Infinite Data for Automated Robot Learning via Generative Simulation 论文作者:Yufei Wang, Zhou Xian, Feng Chen, Tsun-Hsuan Wang, Yian Wang, Zackory Erickson, David Held, Chuang Gan 作者单…

2.26 Qt day4+5 纯净窗口移动+绘画事件+Qt实现TCP连接服务+Qt实现连接数据库

思维导图 Qt实现TCP连接 服务器端&#xff1a; widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include<QTcpServer>//服务器端类 #include<QTcpSocket>//客户端类 #include<QMessageBox>//消息对话框类 #include<QList>//链…

笔记72:关于IMU(惯性测量单元)传感器的作用【不涉及公式推导】

一、IMU传感器是什么&#xff1a; 惯性测量单元IMU&#xff08;Inertial Measurement Unit&#xff09;是一种使用【加速度计】和【陀螺仪】来测量【物体三轴姿态角&#xff08;空间姿态&#xff09;】的装置&#xff1b;IMU在坐标系的每个坐标轴上&#xff0c;均安装有1个陀螺…

分销小程序的常见功能

分销小程序是一种非常有前景和潜力的产品形式&#xff0c;可以帮助企业快速拓展销售渠道&#xff0c;增加销售额。下面我将介绍分销小程序的常见功能。 1. **分销商注册与管理**&#xff1a;支持任何用户自动成为分销商&#xff0c;也可以支持有会员等级&#xff08;或付费或审…

计算机网络:IP

引言&#xff1a; IP协议是互联网协议族中的核心协议之一&#xff0c;负责为数据包在网络中传输提供路由寻址。它定义了数据包如何在互联网上从源地址传输到目的地址的规则和流程。IP协议使得各种不同类型的网络设备能够相互通信&#xff0c;实现了全球范围内的信息交换。 目录…

第三百七十八回

文章目录 1. 概念介绍2. 实现方法2.1 maskFilter2.2 shader 3. 代码与效果3.1 示例代码3.2 运行效果 4. 内容总结 我们在上一章回中介绍了"两种阴影效果"相关的内容&#xff0c;本章回中将介绍如何绘制阴影效果.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概…

StarRocks实战——携程酒店实时数仓

目录 一、实时数仓 二、实时数仓架构介绍 2.1 Lambda架构 2.2 Kappa架构 三、携程酒店实时数仓架构 3.1 架构选型 3.2 实时计算引擎选型 3.3 OLAP选型 四、携程酒店实时订单 4.1 数据源 4.2 ETL数据处理 4.3 应用效果 4.4 总结 原文大佬的这篇实时数仓建设案例有借…

nebula容器方式安装:docker 安装nebula到windows

感谢阅读 基础环境安装安装docker下载nebula 安装数据库命令行安装查询network nebula-docker-compose_nebula-net并初始化查询安装初始使用root&#xff08;God用户类似LINUX的root&#xff09; 关闭服务 安装UI 基础环境安装 安装docker 点我下载docker 下载nebula 数据…

Sentinel实战(待完善)

目录 服务雪崩 什么是服务雪崩 服务不可用原因 解决方案 技术选型对比 Sentinel 介绍 优点 核心概念 资源 规则 代码实战 API实现 SentinelResource注解实现 Sentinel控制台 启动控制台服务 java应用接入控制台 微服务接入Sentinel 服务雪崩 什么是服务雪崩…

1、docker入门

文章目录 1、tocker简介2、tocker的安装&环境配置2、配置阿里云镜像3、基本命令1、镜像命令2、docker基本命令3、镜像基本命令4、Docker 容器常用命令 1、tocker简介 新一代的虚拟化技术 2、tocker的安装&环境配置 uname -r1、首先查看liunx的内核 yum update -y2、更…

uniapp npx update-browserslist-db@lates 问题解决

在uniapp运行项目时&#xff0c;会有这种报错&#xff0c;其实这是表明browserslistlatest版本低了&#xff0c;在催你升级版本&#xff0c;browserslistlatest是用来支持解析css用的&#xff0c;当然&#xff0c;你也可以直接忽略这个报错提示&#xff0c;也可以正常运行项目。…

【AIGC】OpenAI推出王炸级模型sora,颠覆AI视频行业(2024)

对于OpenAI推出的Sora模型&#xff0c;我们可以进一步探讨其可能的技术细节、潜在应用以及对AI视频行业的影响。 点击以下任一云产品链接&#xff0c;跳转后登录&#xff0c;自动享有所有云产品优惠权益&#xff1a; 经过笔者亲测&#xff0c;强烈推荐腾讯云轻量应用服务器作…

day05_用户管理minIO角色分配(页面制作,查询用户,添加用户,修改用户,删除用户,用户头像,查询所有角色,保存角色数据)

文章目录 1 用户管理1.1 页面制作1.2 查询用户1.2.1 需求说明1.2.2 后端接口需求分析SysUserSysUserDtoSysUserControllerSysUserServiceSysUserMapperSysUserMapper.xml 1.2.3 前端对接实现思路sysUser.jssysRole.vue 1.3 添加用户1.3.1 需求说明1.3.2 页面制作1.3.3 后端接口…

ky10-server docker 离线安装包、离线安装

离线安装脚本 # ---------------离线安装docker------------------- rpm -Uvh --force --nodeps *.rpm# 修改docker拉取源为国内 rm -rf /etc/docker mkdir -p /etc/docker touch /etc/docker/daemon.json cat >/etc/docker/daemon.json<<EOF{"registry-mirro…

力扣hot100题解(python版48-50题)

48、路径总和III 给定一个二叉树的根节点 root &#xff0c;和一个整数 targetSum &#xff0c;求该二叉树里节点值之和等于 targetSum 的 路径 的数目。 路径 不需要从根节点开始&#xff0c;也不需要在叶子节点结束&#xff0c;但是路径方向必须是向下的&#xff08;只能从…

力扣hot100题解(python版41-43题)

41、二叉树的层序遍历 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;[[3],[9,20],[15,7]]示例…

Unity将4个纹理图拼接成1个纹理

需要的效果 最终实现的效果大概如下: 4个贴图上去 这里随便放一个切分的图。 Shader代码如下 直接上代码: // Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)// Unlit shader. Simplest possible textured shad…

DFA还原白盒AES密钥

本期内容是关于某app模拟登录的,涉及的知识点比较多,有unidbg补环境及辅助还原算法,ida中的md5以及白盒aes,fart脱壳,frida反调试 本章所有样本及资料均上传到了123云盘 llb资料官方版下载丨最新版下载丨绿色版下载丨APP下载-123云盘 目录 首先抓包 fart脱壳 加密位置定位…