golang 读写锁 sync.RWMutex

阿斯顿法 · · 985 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

golang 读写锁 sync.RWMutex

之前的博客讲了使用互斥锁 sync.Mutex 来保证同一个时刻只有一个goroutine可以访问临界区(内部有共享变量)。当时更多时候,goroutine不是要修改共享变量,只是要读取就行,而互斥锁是完全互斥的。针对这种情况,golang中提供了读写锁 **sync.RWMutex ** ——它 不限制资源的并发读,但是读写、写写操作无法并行执行,这种锁叫作“多读单写”锁(multiple readers, single writer lock)。

  • 写操作使用 sync.RWMutex.Locksync.RWMutex.Unlock 方法;
  • 读操作使用 sync.RWMutex.RLocksync.RWMutex.RUnlock方法;

写锁

加写锁

当资源的使用者想要获取写锁时,需要调用 sync.RWMutex.Lock 方法:

  1. 阻塞后续的写操作
  2. 阻塞后续的读操作
  3. 如果仍然有其他 Goroutine 持有互斥锁的读锁,该 Goroutine 进入休眠状态等待所有读锁所有者执行结束后,将当前协程唤醒
  4. 获取写锁时会先阻塞写锁的获取,后阻塞读锁的获取,这种策略能够保证读操作不会被连续的写操作『饿死』。

解写锁

写锁的释放会调用 sync.RWMutex.Unlock

  1. 调用 sync/atomic.AddInt32 函数将 readerCount 变回正数,释放读锁;
  2. 通过 for 循环释放所有因为获取读锁而陷入等待的 Goroutine:
  3. 调用 sync.Mutex.Unlock 释放写锁;

读锁

读锁的加锁方法 sync.RWMutex.RLock很简单,该方法会通过 sync/atomic.AddInt32readerCount 加一:

  1. 如果其他 Goroutine 获得了写锁,当前 Goroutine 就会陷入休眠等待锁的释放;

当 Goroutine 想要释放读锁时,会调用 sync.RWMutex.RUnlock 方法

读锁和写锁的关系:

  • 调用sync.RWMutex.Lock尝试获取写锁时;
    • 每次 sync.RWMutex.RUnlock 都会将 readerCount 其减一,当它归零时该 Goroutine 会获得写锁;
    • readerCount 减少 rwmutexMaxReaders 个数以阻塞后续的读操作;
  • 调用 sync.RWMutex.Unlock 释放写锁时,会先通知所有的读操作,然后才会释放持有的互斥锁;

有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:阿斯顿法

查看原文:golang 读写锁 sync.RWMutex

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

985 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传