golang sync锁详解

本文详细介绍了Golang中的sync包中的Mutex和RWMutex。Mutex包括数据结构、加锁解锁原理及饥饿模式。RWMutex则讨论了其数据结构、写锁与读锁的获取和释放过程,以及总结了读写锁的特点。
摘要由CSDN通过智能技术生成

sync锁

一、Mutex

数据结构

type Mutex struct {
   
 state int32 // 表示当前互斥锁的状态
 sema  uint32 // 用于控制锁状态的信号量
}

state的基本信息:

  • Locked互斥锁的锁定状态

  • Woken表示从正常模式被从唤醒;

    当一个协程调用 Mutex.Lock() 时,如果 Mutex 已经被其他协程锁定,则该协程将被阻塞,并等待 Mutex 被释放。当其他协程调用 Mutex.Unlock() 释放 Mutex 时,如果等待的协程存在,则会设置 “woken” 标志,以通知等待的协程可以再次尝试获取 Mutex。这样,被阻塞的协程就可以继续执行下去,而不必一直等待下去。

  • Starving 当前的互斥锁进入饥饿状态;

  • waitersCount 当前互斥锁上等待的 Goroutine 个数;

模式

  • 普通模式
    • 锁的等待者会按照先进先出的顺序获取锁。
    • 刚被唤起的 Goroutine 与新创建的 Goroutine 竞争时,大概率会获取不到锁
  • 饥饿模式
    • 互斥锁会直接交给等待队列最前面的 Goroutine。
    • 新的 Goroutine 在该状态下不能获取锁、也不会进入自旋状态,只会在队列的末尾等待。
    • 如果一个 Goroutine 获得了互斥锁并且它在队列的末尾或者它等待的时间少于 1ms,那么当前的互斥锁就会切换回正常模式

加锁 Lock()

源码分析

func (m *Mutex) Lock() {
   
	// 当锁的状态是 0 时,将 mutexLocked 位置成 1
	if atomic.CompareAndSwapInt32(&m.state, 0, mutexLocked) {
   
		return
	}
	// 不是 0 时 尝试通过自旋(Spinnig)等方式等待锁的释放
	m.lockSlow()
}
  • 自旋操作的流程
    • 判断当前 Goroutine 能否进入自旋;
      • 互斥锁只有在普通模式才能进入自旋;
      • 运行在多 CPU 的机器上;
      • 当前 Goroutine 为了获取该锁
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值