评论

收藏

[JavaScript] go语言学习笔记34 Mutex源码分析

开发技术 开发技术 发布于:2021-12-31 19:59 | 阅读数:385 | 评论:0

概述
互斥锁是并发程序中对共享资源进行访问控制的主要手段,Mutex是go语言提供的简单易用的互斥锁。Mutex的结构很简单,暴露的方法也只有2个,一个加锁 一个解锁。那么我们每天用的Mutex互斥锁是如何实现的呢?
DSC0000.png
互斥锁的实现其实就是争夺Locked,当goroutineA 抢到了锁之后,第二个GoroutineB获取锁则会被阻塞等到GoroutineA释放锁之后GoroutineB将会被唤醒。当然具体实现则不会有这么简单,其中还有饥饿模式,自旋函数等一些概念。
+++++++++++++++++++++++++++++++++++++++++++
前置概念
自旋
什么是自旋
加锁时,如果当前Locked位为1,说明该锁当前由其他协程持有,尝试加锁的协程并不是马上转入阻塞,而是会持续的探测Locked位是否变为0,这个过程即为自旋过程。自旋时间很短,但如果在自旋过程中发现锁已被释放,那么协程可以立即获取锁。此时即便有协程被唤醒也无法获取锁,只能再次阻塞。
自旋的好处是,当加锁失败时不必立即转入阻塞,有一定机会获取到锁,这样可以避免协程的切换。
自旋的问题
如果自旋过程中获得锁,则马上执行该goroutine。如果永远在自旋模式中那么之前阻塞的goroutine则很难获得锁,这样一来一些goroutine则会被阻塞时间过长。如何解决这个问题,go mutex中引入了两种模式,具体请看下文。
Mutex的两种模式
普通模式
在普通模式下等待者以 FIFO 的顺序排队来获取锁,但被唤醒的等待者发现并没有获取到 mutex,并且还要与新到达的 goroutine 们竞争 mutex 的所有权。
饥饿模式
在饥饿模式下,mutex 的所有权直接从对 mutex 执行解锁的 goroutine 传递给等待队列前面的等待者。新到达的 goroutine 们不要尝试去获取 mutex,即使它看起来是在解锁状态,也不要试图自旋。








关注下面的标签,发现更多相似文章