互斥锁mutex的简单实现

2023-05-16

mutex一般用于为一段代码加锁,以保证这段代码的原子性(atomic)操作,即:要么不执行这段代码,要么将这段代码全部执行完毕。

例如,最简单的并发冲突问题就是一个变量自增1:

balance = balance + 1;

表面看这是一条语句,可是在背后的汇编中我们可以看到,指令集操作过程中会引入中间变量来保存右边的值,进而这个操作至少会被扩充为:

int tmp = balance + 1;
balance = tmp;

这就需要一把互斥锁(mutual exclusive, mutex)将这段代码给锁住,使其达到任何一个线程“要么全部执行上述代码,要么不执行这段代码”的效果。这个用法可以表示为:

lock_t mutex;
...
lock(&mutex)
    balance = balance + 1;
unlock(&mutex);

那么,一个自然的问题便是,我如何实现上面的这个lock()函数呢?

乍一看这个问题是非常复杂的,特别是考虑到它能够被适用于各种代码的各种情况。但经过各种简化,这个lock()实现,可以通过几个test和set的组合得以实现。

例如,

typedef struct __lock_t { int flag; } lock_t;

void init(lock_t *mutex) {
    // 0: lock is available
    // 1: lock is held
    mutex->flag = 0;
}

void lock(lock_t *mutex) {
    while (mutex->flag == 1) {  // Test the flag.
        ;    // Wait the lock
    mutex->flag = 1;  // Set the lock, i.e. start to hold lock
}

void unlock(lock_t *mutex) {
    mutex->flag = 0;
}

我第一次看到这个算法的时候非常惊讶,一个本来极其复杂的问题就这么优雅地被解决了。它仅仅涉及到对条件的检验和变量的复制,然后整个问题就这么轻而易举地被攻破了。

当然,我并没能看到上述代码的“坑”,也即是必须依靠指令集级别的支持才能真正做到atomic。这同样说明了并发程序的困难,稍微不注意便会调入一个万劫不复的坑里,并且你还不知道哪里出错了。

上述极端优雅的代码,有一个隐藏的坑,那便是在lock()函数的实现里,while循环那一段其实是可以被乱入的。

假设thread A是第一个运行到此的线程,那么它得到的mutex->flag就肯定是0,于是它继续跳出循环往下运行,希望通过下面的mutex->flag = 1来持有锁,使得其它线程在检测while循环时为真,进而进入循环的等待状态。

可如果在A执行到这个赋值为1的语句之前,又有另外一个thread B运行到了这个while循环部分,由于mutex->flag还未被赋值为1,B同样可以跳出while,从而跟A一样拿到这把锁!这就出现了冲突。

那怎么办呢?仔细后可以发现,其实关键问题就在于:

  • mutex->flag的检测
  • mutex->flag的赋值

这两个操作必须是不被干扰的,也就是它必须是atomic的,要么这两段代码不被执行,要么这两段代码被不中断地完整执行。

这就需要借助CPU指令集的帮助,来保证上述两条语句的atomic操作,也即是著名的TestAndSet()操作。

int TestAndSet(int *ptr, int new) {
    int old = *ptr;
    *ptr = new;
    return old;
}

CPU的指令集,并不需要支持繁复的各种atomic操作。仅仅支持上面这个函数,各种互斥加锁的情形,便都能够被涵盖。

此时,在回到我们最开始的那个优雅的lock()实现,就可以将其改造为:

typedef struct __lock_t { int flag; } lock_t;

void init(lock_t *lock) {
    // 0: lock is available
    // 1: lock is held
    mutex->flag = 0;
}

void lock(lock_t *mutex) {
    while (TestAndSet(&lock_t->flag, 1) == 1) {
        ;
}

void unlock(lock_t *lock) {
    lock->flag = 0;
}

上述代码极其精巧。乍一看在lock()实现里不是还缺少一行mutex->flag = 1;么?可其实呢,它已经被整合到了TestAndSet()函数中。

这样的支持TestAndSet()的实现,便是最简单的spin lock,弹簧锁。之所以叫弹簧锁,那是因为在各类锁当中,弹簧锁就是最初的被投入工业使用的最简单的实现技术。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

互斥锁mutex的简单实现 的相关文章

  • 解决docker-compose 命令不存在、未找到命令错误

    1 安装扩展源 sudo yum y install epel release 2 安装python pip模块 sudo yum install python pip 3 查看docker compose版本 docker compose
  • 团队项目中应如何评价个人对团队的贡献?

    这是一个非常有用的问题 如果不仔细思考这个问题 xff0c 就会造成团队成员的不公平 积极性不高等问题 Shine团队的队员们 xff0c 可以在这篇随笔里畅所欲言 xff0c 我先来 xff1a 王安然 xff1a 对于一个项目来说 xf
  • Hash算法初见

    hash算法 hashmap 实现原理 Hash xff0c 一般翻译做 散列 xff0c 也有直接音译为 哈希 的 xff0c 就是把任意长度的输入 xff08 又叫做预映射 xff0c pre image xff09 xff0c 通过散
  • JS学习笔记

    1 空值 xff1a null xff0c undefined NaN Not a Number e g var bestAge 61 null null var currentCount undefined NaN 作比较时 xff0c
  • linux下C语言socket网络编程简例

    转自 http blog csdn net kikilizhm article details 7858405 这里给出在linux下的简单socket网络编程的实例 xff0c 使用tcp协议进行通信 xff0c 服务端进行监听 xff0
  • linux下ffmpeg的使用方法

    格式转换 将file avi 转换成output flv C代码 ffmpeg i file avi output flv i 表示输入文件 现在有个视频video avi xff0c 有个音频 audio mp3 xff0c 将其合并成o
  • linux ssh登录 Permission denied (publickey)

    可能的原因 xff1a Linux上ssh服务没有开密码登录 目前发现两种解决方案 xff1a 打开密码登录 执行sudo vim etc ssh sshd config 找到PasswordAuthentication一项 xff0c 将
  • c语言:输入一行字符,分别统计出其中英文字母、空格、数字和其他字符的个数。...

    输入一行字符 xff0c 分别统计出其中英文字母 空格 数字和其他字符的个数 解 xff1a 程序 xff1a include lt stdio h gt int main char c int letters 61 0 space 61
  • ubuntu上网慢解决方案-配置dns

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 在ubuntu下用firefox等浏览器上网 往往比在windows下上网要慢好多 但细心的人会发现 慢的时间是花在DNS查找上面了 那么我们可以在本机缓存DNS 也就是在
  • c51按键控制灯亮汇编语言,用一个按键控制LED灯亮/暗的汇编程序

    今天又搞了一个小汇编 xff0c 是用一个按键控制LED灯亮 暗的汇编程序 程序编好后 xff0c 开始编译 xff0c 发现又是通不过 xff0c 找了好几遍也没找到原因 xff0c 后来找枫雪大哥看了 xff0c 才找出原因 xff0c
  • 如何使用linux程序mdadm创建软件RAID1软阵列

    如何使用linux程序mdadm创建软件RAID1软阵列 磁盘冗余阵列 RAID 是将多个物理磁盘结合成一个逻辑磁盘的技术 xff0c 该技术可以提高磁盘容错性能 xff0c 提高磁盘的读写速度 根据数据存储的排列 如 xff1a 条带存储
  • 极乐净土----Android实现图片转ascii码字符图的一些尝试

    掘金第一篇 xff0c 先转一个自己以前的帖子吧 xff0c 懒得重新写了 www jianshu com p 357af674a 转载于 https juejin im post 5c36df2cf265da616624abc6
  • idea中使用FindBugs-IDEA插件

    下载 安装 重启idea即可 xff1b 项目右键或者文件右键即可看到 FindBugs 选项 选择某个选项直接检测即可 检测结果如下图 xff1a 这里的Correctness是重点关注对象 这里面的错误往往是比较严重的 像空指针之类的错
  • pip,virtualenv,conda和anaconda的个人理解

    1 pip pip是python下的包管理工具 xff0c 主要用于从pypi下载所需的python包 xff0c 但是pip不会自动处理包之间的依赖关系 xff1b 在使用pip安装包时 xff0c 可以修改安装源为https pypi
  • Windows Server 2016-Hyper-V网络虚拟化概述

    在 Windows Server 2016 和虚拟机管理器中 xff0c Microsoft 提供的端到端网络虚拟化解决方案 有构成了 Microsoft 的网络虚拟化解决方案的五个主要组件 xff1a Windows Azure Wind
  • mac环境下安装pysvn

    可以从下载页下载对应版本的pysvn xff1a https pysvn sourceforge io downloads html 之后双击打开安装即可 xff0c 不需要再用pip安装 需要注意的是 xff0c 如果安装时提示chdir
  • 关于PHP中Session文件过多的问题

    PHP的默认机制 xff1a 每一次php请求 xff0c 会有1 100的概率 xff08 默认值 xff09 触发 session回收 如果 session回收 发生 xff0c 那就会检查 tmp sess 的文件 xff0c 如果最
  • RDO 远程 桌面无法复制

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 这里是列表文本这里是列表文本首先我们要检查 登录机在进程管理器中是否有rdpclipe exe这个进程 如果有则杀掉 xff0c 如果没有 xff0c 则在任务管理器中菜单
  • 如何在 Excel 中自定义菜单和菜单栏

    Microsoft 提供的编程示例只用于说明目的 xff0c 不附带任何明示或默示的保证 这包括但不限于对适销性或特定用途适用性的默示保证 本文假定您熟悉所演示的编程语言和用于创建和调试过程的工具 Microsoft 的支持工程师可以帮助解
  • 轮环(Ouroboros)世界观介绍,摘自Guide Book

    基于现实的架空世界观 这个游戏的世界观是基于以现代人的眼光来看待自身长久以来的发展与盛衰交替的事实 xff0c 而在此基础上构想出的简化的因果逻辑 xff0c 以及其外在的表现形式 祭祀 游戏根据中国古代的以国家为单位的大规模殉 祭奴隶的事

随机推荐

  • css背景图等比例缩放,盒子随背景图等比例缩放

    很多时候我们给网站了一个大banner 但是随着屏幕的变化 xff0c 背景会变形 xff0c 我们知道background size可以实现背景图等比例缩放 xff0c 但是 xff0c 我们想让下面的盒子根据缩放后背景图的高度 xff0
  • 如何用PS快速的批量制作连续号码数字编号图解

    如何用PS快速的批量制作连续号码数字编号图解 大家好 xff0c 今天太原博飞设计培训小编就告诉大家如用 PS 快速的制作连续数字编号 xff0c 在工作中尤其是大型活动的有时候制作连续的号码牌 xff0c 少还好 xff0c 如果上百上千
  • 我们评测了5个主流跨端框架,这是它们的区别

    最近前端届多端框架频出 xff0c 相信很多有代码多端运行需求的开发者都会产生一些疑惑 xff1a 这些框架都有什么优缺点 xff1f 到底应该用哪个 xff1f 作为 Taro 开发团队一员 xff0c 笔者想在本文尽量站在一个客观公正的
  • 大牛直播SDK-Windows RTMP/RTSP/本地FLV播放器使用说明 ...

    大牛直播播放器SDK相对推送SDK来说 xff0c 接口没有那么多 xff0c 不过客户95 以上的常规需求均已覆盖 xff0c 目前支持RTMP和RTSP直播播放 xff0c 还有本地flv文件回放 xff1a 大牛直播SDK播放端提供C
  • 交换机的配置文件备份到TFTP和FTP服务器

    1 构建拓扑 2 配置地址 Switch gt Switch gt en Switch conf t Switch config hostname 666 修改交换机名字 666 config interface vlan 1 进入虚拟接口
  • 推荐几款常用的Socks5代理软件

    一 Sockscap 荐 SocksCap是目前对网络游戏兼容性最好的代理工具之一 SocksCap32 软件是由美国 NEC USA Inc 公司出品的代理服务器第三方支持软件 拥有功能强大的 SOCKS 调度 xff0c 使用它就可以让
  • Nginx根据post参数转发请求 (OpenResty)

    最近有个需求 xff0c 需要nginx根据POST参数将请求转发到不同的后端 xff0c 调研后决定使用OpenResty xff08 Nginx 43 Lua xff09 作为代理服务器 写个小Demo location span cl
  • Windows 10访问共享时提示“过时的SMB1协议”的修复办法

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 公司有台Windows XP老版本系统的文件共享服务器 xff0c 前段时间好好的能正常访问 xff0c 今天访问时突然提示 因为文件共享不安全 xff0c 所以你不能连接
  • 关于Video Src 带有 blob:http的视频如何下载的问题

    我们如果使用爬虫 xff0c 想爬取一些视频的时候 xff0c 会发现一些网站提供的视频链接打开是 404 xff1b span class hljs tag lt span class hljs name video span span
  • Wcf 双工通信的应用

    概述 双工 xff08 Duplex xff09 模式的消息交换方式体现在消息交换过程中 xff0c 参与的双方均可以向对方发送消息 基于双工MEP消息交换可以看成是多个基本模式下 xff08 比如请求 回复模式和单项模式 xff09 消息
  • Foxit PDF Reader能有效升级日文包

    Foxit Reader 原名 Foxit PDF Reader xff0c 是一款 PDF文档阅读软件 xff0c 它具有比Adobe Reader更加小巧的身材 xff0c 更加快速的速度 xff0c 以及更加丰富的插件 xff0c 完
  • JIRA学习

    Jira是Atlassian公司出品的一款事务管理软件 无论是 需求 xff0c 还是 BUG xff0c 或是 任务 xff0c 都是 事务 的一种 xff0c 所以Jira可以胜任非常多的角色 xff1a 需求管理 缺陷跟踪 任务管理等
  • python 面向对象编程

    面向对象与面向过程 参考链接 xff1a https www liaoxuefeng com wiki 0014316089557264a6b348958f449949df42a6d3a2e542c000 0014318645694388f
  • pycharm调整代码长度分割线

    1 File gt Settings gt Code Style gt Right margin columns 的值为80 xff0c 大功告成 2 具体设置的数值可以根据个人电脑的屏幕大小而定 xff0c 如果屏幕比较大可以设置的长一些
  • ppt点击文字出现图片,再次点击消失

    实现效果 xff1a 在PPT一个页面的任意位置 xff0c 单击左键 xff0c 出现图片 xff1b 在图片上 xff0c 单击左键 xff0c 图片消失 实现思路 xff1a 给图片做两个动画 xff0c 一个进入 xff0c 文字作
  • OC中APPDelegate[[UIApplication shareApplication]delegate]]Swift实现

    直接上代码 xff1a var myDelegate AppDelegate myDelegate 61 UIApplication sharedApplication delegate as AppDelegate
  • 安装好Pycharm后如何配置Python解释器简易教程

    这两天有许多Python小白加入学习群 xff0c 并且问了许多关于Pycharm基本使用的问题 xff0c 今天小编就以配置Python解释器的问题给大家简单絮叨一下 1 一般来说 xff0c 当我们启动Pycharm xff0c 如果P
  • MySQL net start mysql 发生系统错误5 解决办法

    产生的原因是权限不够 用管理员权限打开命令提示符就OK 啦 Win10解决办法 xff1a 使用快捷键win 43 x xff0c 或右击开始图标 xff0c 打开命令提示符 xff08 管理员 xff09 就解决啦
  • Docker查看远端仓库的标签工具

    背景 最近入坑了docker xff0c 比如本地想要启动一个elastic容器的话 xff0c 直接通过以下命令即可快速启动一个elasticsearch的实例 docker run d p 9200 9200 p 9300 9300 n
  • 互斥锁mutex的简单实现

    mutex一般用于为一段代码加锁 xff0c 以保证这段代码的原子性 xff08 atomic xff09 操作 xff0c 即 xff1a 要么不执行这段代码 xff0c 要么将这段代码全部执行完毕 例如 xff0c 最简单的并发冲突问题