文本描述
2020/10/28 01 | Mutex:如何解决资源并发访问问题? 下载APP 01 | Mutex:如何解决资源并发访问问题? 2020-10-12 晁岳攀 Go 并发编程实战课 进入课程 讲述:安晓辉 时长 16:29 大小 15.10M 你好,我是鸟窝。 今天是我们 Go 并发编程实战课的第一讲,我们就直接从解决并发访问这个棘手问题入 手。 说起并发访问问题,真是太常见了,比如多个 goroutine 并发更新同一个资源,像计数 器;同时更新用户的账户信息;秒杀系统;往同一个 buffer 中并发写入数据等等。如果没 有互斥控制,就会出现一些异常情况,比如计数器的计数不准确、用户的账户可能出现透 支、秒杀系统出现超卖、buffer 中的数据混乱,等等,后果都很严重。 这些问题怎么解决呢?对,用互斥锁,那在 Go 语言里,就是 Mutex。 time.geekbang/column/article/294905?utm_source=time_web&utm_medium=menu&utm_term=timewebmenu 1/18 2020/10/28 01 | Mutex:如何解决资源并发访问问题? 这节课,我会带你详细了解互斥锁的实现机制,以及 Go 标准库的互斥锁 Mutex 的基本使 用方法。在后面的 3 节课里,我还会讲解 Mutex 的具体实现原理、易错场景和一些拓展用 法。 好了,我们先来看看互斥锁的实现机制。 互斥锁的实现机制 互斥锁是并发控制的一个基本手段,是为了避免竞争而建立的一种并发控制机制。在学习 它的具体实现原理前,我们要先搞懂一个概念,就是临界区。 在并发编程中,如果程序中的一部分会被并发访问或修改,那么,为了避免并发访问导致 的意想不到的结果,这部分程序需要被保护起来,这部分被保护起来的程序,就叫做临界 区。 可以说,临界区就是一个被共享的资源,或者说是一个整体的一组共享资源,比如对数据 库的访问、对某一个共享数据结构的操作、对一个 I/O 设备的使用、对一个连接池中的连 接的调用,等等。 如果很多线程同步访问临界区,就会造成访问或操作错误,这当然不是我们希望看到的结 果。所以,我们可以使用互斥锁,限定临界区只能同时由一个线程持有。 当临界区由一个线程持有的时候,其它线程如果想进入这个临界区,就会返回失败,或者 是等待。直到持有的线程退出临界区,这些等待线程中的某一个才有机会接着持有这个临 界区。 time.geekbang/column/article/294905?utm_source=time_web&utm_medium=menu&utm_term=timewebmenu 2/18 2020/10/28 01 | Mutex:如何解决资源并发访问问题? 你看,互斥锁就很好地解决了资源竞争问题,有人也把互斥锁叫做排它锁。那在 Go 标准 库中,它提供了 Mutex 来实现互斥锁这个功能。 根据 2019 年第一篇全面分析 Go 并发 Bug 的论文Understanding Real-World Concurrency Bugs in Go,Mutex 是使用最广泛的同步原语(Synchronization primitives,有人也叫做并发原语。我们在这个课程中根据英文直译优先用同步原语,但是 并发原语的指代范围更大,还可以包括任务编排的类型,所以后面我们讲 Channel 或者扩 展类型时也会用并发原语)。关于同步原语,并没有一个严格的定义,你可以把它看作解 决并发问题的一个基础的数据结构。 在这门课的前两个模块,我会和你讲互斥锁 Mutex、读写锁 RWMutex、并发编排 WaitG