Go语言之RWMutex

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

转自“灰子学技术”,原文链接:https://mp.weixin.qq.com/s/0nfjNsFNIrMhYJMf3P-sEw

本篇文章,笔者主要来介绍读写锁的一种Go语言的实现方式RWMutex。

1.基本概念

读写锁:是计算机程序的并发控制的一种同步机制,也称“共享-互斥锁”、多读者-单写者锁。读操作可并发重入,写操作是互斥的。

主要适用的场景是:读多写少的业务场景。这种场景下如果每次读写都使用互斥锁那么整个效率就会变得很低。因为只是读的话并不需要互斥锁来锁住数据,只有写操作的时候需要互斥锁,而读写结合的时候,也是需要加锁的,不然的话会导致读的数据不一定是期望的。

对于RWMutex的规则如下:

1、可以随便读,多个goroutine同时读。

2、写的时候,不能读也不能写。

主要有下面四个API构成,读锁RLock,RUnlock,写锁Lock,Unlock。

2.实例分析

对于读写锁来说,可以拆分成下面四种情况:

1)读事件结束之后,写事件到达。 2)读事件进行的过程中,写事件到达 。 3)写事件完成之后,读事件到达。  4)写事件进行的过程中,读事件到达。5) 只有读的操作。6)只有写的操作。

对于1)和3)来说,读事件和写事件是顺序执行的,不会出现相互影响的问题,我们主要来看下2),4), 5),6)两种情况的例子。

2.1 例子1, 只有读的操作:

结果分析:通过运行的结果我们可以看出来,多个读操作不需要等到前一个读事件结束了,才去执行下一个读事件, 所以一旦我们在RLock和RUnlock之间修改共享变量num的时候,有两个协程5号和3号会读到相同的数值3。

2.2 例子2, 只有写的操作:

结果分析:只有写操作的时候,每一次执行的结果num都是递增的,不会出现乱序,这就说明,写锁的加锁和解锁是互斥的,必需一个加锁和解锁结束了,才执行下一次。

2.3 例子3,读事件进行的过程中,写事件到达:

结果分析:通过上面的输出结果,我们可以看出写事件的goroutinue在2号读数据的goroutinue结束就开始启动了,因为其他的读协程已经用读锁锁住了,所以在这些调用了读锁的这些读协程都释放了读锁之后,写锁才开始从 阻塞中被拿出来重新执行。

2.4 例子4,写事件进行的过程中,读事件到达

结果分析:从结果可以看出,一旦写操作的协程开始加锁,读操作的读锁的加锁操作只能在写锁释放之后,才会执行。

3.小结:

通过上面的例子,我们可以看出:1)多个读锁可以同时操作 。2)写锁一旦加锁,不管是读操作还是写操作都不能被执行。3)读锁加锁了之后,只要读锁还没有解锁,写操作是不能被执行的。

参看文档:

rwmutex源码:https://golang.org/src/sync/rwmutex.go?s=987:1319#L18

Go RWMutex 源码学习:https://studygolang.com/articles/22356

维基百科-读写锁:https://zh.wikipedia.org/wiki/%E8%AF%BB%E5%86%99%E9%94%81

灰子学技术:

 


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

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

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