首页 > 其他分享 >golang Sync.Mutex互斥锁和Sync.RWMutex读写锁小结

golang Sync.Mutex互斥锁和Sync.RWMutex读写锁小结

时间:2022-08-16 15:12:16浏览次数:75  
标签:writer RWMutex goroutine Sync 互斥 Mutex 唤醒

Sync.Mutex

一、结构体

type Mutex struct {
  state int32  // 互斥锁的状态:被g持有,空闲等
  sema  uint32 // 信号量,用于阻塞/唤醒 goroutine(协程)
}
//使用
  var mtx sync.Mutex
  mtx.Lock()
  mtx.Unlock()

这里的 state 字段是 int32 类型,但是它被分为了4 部分操作,为了使用更少的内存去表达锁的各个状态

二、正常模式和饥饿模式

正常模式自旋和排队同时存在的,执行Lock的goroutine会先一边自旋,尝试过几次后还没拿到锁,就需要去排队等待了。这种在排队之前先让大家来抢的模式,能够有更高的吞吐量,因为频繁的挂起、唤醒goroutine会带来较多的开销。但又不能无限制的自旋,要把自旋的开销控制在较小的范围内。所以在正常模式下,Mutex有更好的性能,但是可能会出现队列尾端的goroutine迟迟抢不到锁(尾端延迟)的情况。而饥饿模式下不在自旋尝试,所有goroutine都要排队,严格的先来后到,对于防止出现尾端延迟来讲特别重要

  1. normal 模式下:
    1. 加入了竞争的情况,被唤醒的 g 可能会与刚到来的 g 一起竞争锁,但是被唤醒的 g 很可能失败。因为 g 被唤醒就说明锁已经被释放了,那么自旋的很可能已经获得锁了
    2. 睡眠时间超过 1ms 的 g,被唤醒后想要将 mutex 切换为 starving 模式,切换后也会再次进入阻塞队列且排在队列头部,等待锁的释放别唤醒
  2. starving 模式下:
    1. 只有被唤醒的等待者才能加锁,其他的 g 全都进入 FIFO 阻塞队列

谨记:在原子操作处,所有的 g 都会是串行化(序列化)的。

三、Mutex.Lock()

原子操作atomic.CompareAndSwapInt32(&m.state, 0, mutexLocked)

原子操作确保其它处理器或者核总是访问原子操作之后的最新的值;虽然有 cache 的存在,内存屏障解决,必须要要等到内存屏障管道中的未完成数据都刷新到内存中,再进行操作,而且此操作会让相关的 cpu 的缓存行失效(cpu 缓存一致性协议)。

四、Mutex.UnLock()

所以尽量做到谁 Lock 谁 UnLock,做到谁申请,就由谁释放。一般都是在同一个方法中使用。

Unlock 方法可以被任意的 goroutine 调用释放锁,即使是没持有这个互斥锁的 goroutine,也可以进行这个操作。这是因为,Mutex 本身并没有包含持有这把锁的 goroutine 的信息,所以,Unlock 也不会对此进行检查。

Sync.RWMutex

一、结构体

type RWMutex struct {
w           Mutex  // 互斥锁

writerSem   uint32 // reader 完成后会释放 writer信号量

readerSem   uint32 // writer 完成后会释放 reader 信号量

readerCount int32  // 当前的 reader 的数量(以及用来判断是否有 writer 线程请求锁或者持有锁)

readerWait  int32  // writer 等待 reader 完成的数量,到 0,writer 会被唤醒
}


const rwmutexMaxReaders = 1 << 30 // 表识最大 reader 线程数量

//使用

RLock、RUnLock、Lock、UnLock

RLock方法将rw锁定为读取状态,禁止其他线程写入,但不禁止读取。

标签:writer,RWMutex,goroutine,Sync,互斥,Mutex,唤醒
From: https://www.cnblogs.com/ling11/p/16591632.html

相关文章

  • HttpClient.PatchAsJsonAsync - dotnet/runtime 项目贡献小记
    TL;DR迫于PatchAsJsonAsync方法缺失,我给dotnet/runtime项目贡献了相关的API,可惜要到.NET7才能用上。https://github.com/dotnet/runtime/pull/60672正文同事小......
  • 如何让 useEffect 支持 async...await?
    本文是深入浅出ahooks源码系列文章的第六篇,该系列已整理成文档-地址。觉得还不错,给个star支持一下哈,Thanks。本文已收录到个人博客中,欢迎关注~背景大家在使用useEf......