go

Go 系列 Mutex深入解析

Posted by lichao modified on December 27, 2021

源码详解

Mutex 的结构体很简单,存在两个字段:state(状态),sema(信号量)。

1
2
3
4
5
6
7
8
9
10
11
12
13
type Mutex struct {
 state int32  // 状态
 sema  uint32 // 信号量
}

// 下文代码中用到的几个常量
const (
 mutexLocked = 1 << iota // 1,锁标志
 mutexWoken    // 2,唤醒标志
 mutexStarving  // 4,饥饿标志
 mutexWaiterShift = iota //3,等待队列长度
 starvationThresholdNs = 1e6
)

首先 Mutex 就只有两个变量,一个表示状态,一个是信号量,非常简洁。 mutex的状态机比较复杂,使用一个int32来表示:

Mutex

最低三位分别表示 mutexLocked、mutexWoken 和 mutexStarving,剩下的位置用来表示当前有多少个 Goroutine 等待互斥锁的释放。

在默认情况下,互斥锁的所有状态位都是 0,int32 中的不同位分别表示了不同的状态:

  • mutexLocked — 表示互斥锁的锁定状态;
  • mutexWoken — 表示从正常模式被从唤醒;
  • mutexStarving — 当前的互斥锁进入饥饿状态;
  • waitersCount — 当前互斥锁上等待的 goroutine 个数;

为了保证锁的公平性,设计上互斥锁有两种状态:正常状态和饥饿状态。