Go 并发编程实战课
晁岳攀(鸟窝)
前微博技术专家,知名微服务框架 rpcx 作者
25635 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 22 讲
Go 并发编程实战课
15
15
1.0x
00:00/00:00
登录|注册

01 | Mutex:如何解决资源并发访问问题?

封装方法
Mutex的嵌入使用
Mutex的零值
使用Mutex解决data race问题
例子:并发访问场景中不使用锁的问题
Lock和Unlock方法
Locker接口
互斥锁的作用
临界区
思考题
总结
Mutex的基本使用方法
互斥锁的实现机制
Mutex

该思维导图由 AI 生成,仅供参考

你好,我是鸟窝。
今天是我们 Go 并发编程实战课的第一讲,我们就直接从解决并发访问这个棘手问题入手。
说起并发访问问题,真是太常见了,比如多个 goroutine 并发更新同一个资源,像计数器;同时更新用户的账户信息;秒杀系统;往同一个 buffer 中并发写入数据等等。如果没有互斥控制,就会出现一些异常情况,比如计数器的计数不准确、用户的账户可能出现透支、秒杀系统出现超卖、buffer 中的数据混乱,等等,后果都很严重。
这些问题怎么解决呢?对,用互斥锁,那在 Go 语言里,就是 Mutex。
这节课,我会带你详细了解互斥锁的实现机制,以及 Go 标准库的互斥锁 Mutex 的基本使用方法。在后面的 3 节课里,我还会讲解 Mutex 的具体实现原理、易错场景和一些拓展用法。
好了,我们先来看看互斥锁的实现机制。

互斥锁的实现机制

互斥锁是并发控制的一个基本手段,是为了避免竞争而建立的一种并发控制机制。在学习它的具体实现原理前,我们要先搞懂一个概念,就是临界区
在并发编程中,如果程序中的一部分会被并发访问或修改,那么,为了避免并发访问导致的意想不到的结果,这部分程序需要被保护起来,这部分被保护起来的程序,就叫做临界区。
可以说,临界区就是一个被共享的资源,或者说是一个整体的一组共享资源,比如对数据库的访问、对某一个共享数据结构的操作、对一个 I/O 设备的使用、对一个连接池中的连接的调用,等等。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文深入介绍了互斥锁在并发编程中的重要性和基本概念,以及其在解决并发访问问题中的作用。通过讨论并发访问问题的常见场景,阐述了互斥锁在保护临界区共享资源时的重要性,以及避免资源竞争导致错误的必要性。特别强调了Go语言标准库中的Mutex在解决并发问题中的广泛应用。此外,还介绍了同步原语的适用场景,包括共享资源的读写、任务编排和消息传递。通过学习互斥锁,读者可以深入了解并发编程中的基本原理和常见工具,为解决并发访问问题提供了重要参考。文章还介绍了使用互斥锁解决并发访问共享资源的问题,并介绍了Go语言中的race detector工具,以及如何使用互斥锁来消除data race问题。最后,通过示例代码展示了如何使用互斥锁来保护共享资源,避免并发访问问题。文章内容全面介绍了互斥锁在并发编程中的重要作用和基本用法,对读者快速了解并发编程提供了重要参考。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Go 并发编程实战课》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(65)

  • 最新
  • 精选
  • Panmax
    原文中关于 race detector 的介绍有两句话前后矛盾,老师可否解释一下: 前边说:在编译(compile)、测试(test)或者运行(run)Go 代码的时候,加上 race 参数,就有可能发现并发问题。 后边却又说:因为它的实现方式,只能通过真正对实际地址进行读写访问的时候才能探测,所以它并不能在编译的时候发现 data race 的问题。 所以结论是 race detector 并不能在编译阶段发现并发问题?那么前边那句是不是就没必要提了,不然容易让大家误会。

    作者回复: 那借这个问题解答一下吧。编译的时候不能发现data race,但是编译的时候可以开启race参数,这样编译后的程序在运行时就可以data race问题了。你看到很仔细,希望这个解答能把这段解释清楚。 另外,绝对不要把带race参数编译的程序部署到线上。

    2020-10-18
    4
    26
  • pedro
    大家都已经解答了,就不重复了。这里给一些不熟悉 go 需要的同学补充一下,go 语言查看汇编代码命令: go tool compile -S file.go 对于文中 counter 的例子可以过度优化一下,那就是获取计数的 Count 函数其实可以通过读写锁,也就是 RWMutex 来优化一下。

    作者回复: 你居然“剧透”第五讲的内容������

    2020-10-13
    5
    19
  • 骁勇善战
    老师,为什么读也要加锁呢?

    作者回复: 说来话长。 1.mutex保护的临界区。如果读的时候不加锁,可能会造成不一致的后果,比如部分变量被修改了。 2.如果临界区比较简单,比如一个int64读写,也可能在一些cpu架构下有可见性问题,导致别的goroutine对变量的写读goroutine看不到

    2021-06-13
    2
    11
  • ZY
    有两种情况 1. 如果当前有协程进入自旋模式,当前协程会成功获取到锁 2. 如果没有协程进入自选模式,释放锁的协程会释放的信号量会成功唤醒等待队列中的协程,该卸程会成功获取到锁,并且把等待计数器减1. 老师:在饥饿模式下,信号量唤醒的协程成功获取到锁之后,该Mutex的模式会改变吗?

    作者回复: 进入自旋不一定会获取到锁。 饥饿模式不一定改变,看文章。只有等待时间小于阈值或者无等待者时才会改变模式

    2020-10-17
    7
  • 一代咩神
    能否解答一下,为什么获取计数器的值也需要加锁?

    作者回复: 否则获取的时候可能不能得到刚增加的值

    2021-01-14
    5
  • chapin
    个人希望🐤 窝大佬可以多分析一些源码。

    作者回复: 明天一讲剖析mutex

    2020-10-13
    4
  • 无名无姓
    请问老师goroutine里面自旋怎么理解

    作者回复: 一直尝试做获取锁,而不是让渡cpu给其他goroutine

    2021-10-10
    3
  • 初学者
    老师好,“多个goroutine并发更新同一个资源”,这里的同一个资源的条件是不是应该是堆栈分析后分配到堆上的变量,因为堆上是线程共享的,如果是栈上的变量的话,因为是线程独有的就不会出现并发更新的问题,望老师解答下

    作者回复: 对

    2021-05-27
    3
  • Singin in the Rain
    在Go 1.20之后的版本,执行命令『go tool compile -race -S counter.go』会报如下的错误: could not import fmt (file not found) could not import sync (file not found) 导致错误的原因是:在Go 1.20之前,标准库被安装到$GOROOT/pkg/$GOOS_$GOARCH。从Go 1.20开始,标准库被构建和缓存但没有安装。可以通过设置GODEBUG=installgoroot=all,然后编译重新安装Go运行环境,恢复$GOROOT/pkg/$GOOS_$GOARCH的使用,但是改动太大。可以通过如下命令解决这个问题: 不带race参数:go build -gcflags=-S counter.go 1> normal.txt 2>&1 带race参数:go build -race -gcflags=-S counter.go 1> race.txt 2>&1 参考链接: https://github.com/golang/go/issues/58629 https://pkg.go.dev/cmd/go https://go.dev/doc/asm

    作者回复: 👍🏻

    2023-04-04归属地:湖北
    1
  • 用了一个内存库 github.com/boltdb/bolt,在用-race 运行的时候,里边一个函数的时候报错 panic类型的,fatal error: checkptr: converted pointer straddles multiple allocations 关键的两行报错 D:/GO/src/runtime/checkptr.go:20 +0xc9 fp=0xc00029f9e8 sp=0xc00029f9b8 p c=0x554b89 github.com/boltdb/bolt.(*freelist).write(0xc0004e5290, 0xc000508000, 0xc00050800 0, 0x0) 百度不出来所以然 老师这东西为啥报错啊 不带race运行好好的

    作者回复: 看看是不是你数据有并发的问题?如果确定不是,那就是bolt的bug了,不过可能性比较小

    2021-09-02
    1
收起评论
显示
设置
留言
65
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部