Go语言中的互斥锁(Mutex)和读写锁(RWMutex)

 Mutex

  Mutex结构体

type Mutex struct {
    state int32 //表示互斥锁的状态,比如是否被锁定等
    sema uint32 //表示信号里,协程阻塞等待的信号量,解锁的协程释放信号量从而唤醒等待信号量的协程
}

  • Locked: 表示Mutex是否已被锁定(1表示已经被锁定)
  • Woken: 表示是否有协程被唤醒(1已有协程唤醒,正在加锁过程中)
  • Starving: 表示Mutex是否处于饥饿状态(1表示饥饿状态,说明有协程阻塞超过1ms)
  • Waiter: 表示阻塞等待锁的协程个数,协程解锁时根据此值来判断是否需要释放洗好了.

协程之间抢锁实际上是抢给Locked赋值的权利,能给Locked值置为1,就说明抢锁成功.抢不到的话就阻塞等待Mutex.sema信号量,一旦持有锁的协程解锁,等到的协程就会被依次唤醒.

Mutex只有两个方法:

  • Lock()加锁
  • Unlock()解锁

加锁被阻塞以及解锁唤醒协程

自旋(CPU的"PAUSE"指令,CPU空转,什么也不做)

加锁时,如果当前Locked为1,说明该锁由其他协程持有,尝试加锁的协程并不是马上转入阻塞,而是会持续的探测Locked位是否变为0,这个过程即为自旋过程.自旋时间很短,但如果自旋过程中发现锁已经被释放,那么协程可以立即获取锁.(可以避免协程间的切片)

Mutex模式

 normal模式

默认情况下,Mutex的模式位normal,该模式下,协程如果加锁不成功不会立即转入阻塞排队,而是判断是否满足自旋条件,如果满足则会启动自旋过程,抢锁.

 starvation模式

自旋过程中能抢到锁的话,说明此时一定有协程释放了锁,释放锁时如果发现有阻塞等待的协程,还会释放一个信号量来唤醒一个等待协程,被唤醒的协程获得CPU开始运行,此时发现锁被抢占,自己再次阻塞,但是如果阻塞时间已经超过1ms,starving将被标记为1(饥饿模式)

饥饿模式下,不会启动自旋过程.

Woken状态

Woken状态用于加锁和解锁过程的通信.

读写锁

type RWMutex struct {
    w           Mutex  //用于控制多个写锁,获得写锁首先要获取该锁,如果有一个写锁在进行,那么再到来的写锁将会阻塞于此
    writerSem   uint32 //写阻塞等待的信号量,最后一个读者释放锁时会释放信号量
    readerSem   uint32 //读阻塞的协程等待的信号量,持有写锁的协程释放锁后会释放信号量
    readerCount int32  //记录读者个数
    readerWait  int32  //记录写阻塞时读者个数
}
接口定义
  • RLock(): 读锁定,等待写操作结束(如果有)
  • RUnlock(): 解除读锁定,唤醒等待写操作的协程(如果有)
  • Lock(): 写锁定,与Mutex完全一致,阻塞等待所有读操作结束(如果有)
  • Unlock(): 解除写锁定,与Mutex一致,唤醒因读锁定而被阻塞的协程(如果有)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值