ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Go面试题(四):锁的实现原理--sync.RWMutex 篇

2021-11-27 18:00:34  阅读:179  来源: 互联网

标签:面试题 RWMutex 读写 sync 读锁 操作 readerCount


大家好,我是小道哥。

上一篇为大家介绍了Go中的sync.Mutex互斥锁的数据结构及实现原理,今天继续为大家介绍另外一种常用的锁,那就是sync.RWMutex读写锁

读写锁的使用

读写互斥锁sync.RWMutex不限制对资源的并发读,但是读写,写写操作无法并行执行。

读写锁一共有四个函数:

  • RLock(): 申请读锁
  • RUnlock(): 解除读锁
  • Lock(): 申请写锁
  • Unlock(): 解除写锁

实现原理

sync.RWMutex的数据结构

Go中sync.RWMutext的结构体为

type RWMutex struct {
	w           Mutex  // 复用互斥锁
	writerSem   uint32 // 写锁监听读锁释放的信号量
	readerSem   uint32 // 读锁监听写锁释放的信号量
	readerCount int32  // 当前正在执行读操作的数量
	readerWait  int32  // 当写操作被阻塞时,需要等待读操作完成的个数
}

接下来,我们结合底层数据结构来分析读写锁是如何实现对资源并发读写的控制的。

  1. 读操作如何防止并发读写问题的?
  • RLock(): 申请读锁,每次执行此函数后,会对readerCount++,此时当有写操作执行Lock()时会判断readerCount>0,就会阻塞。
  • RUnLock(): 解除读锁,执行readerCount–,释放信号量唤醒等待写操作的goroutine。
  1. 写操作如何防止并发读写、并发写写问题?
  • Lock(): 申请写锁,获取互斥锁,此时会阻塞其他的写操作。并将readerCount 置为 -1,当有读操作进来,发现readerCount = -1, 即知道有写操作在进行,阻塞。
  • Unlock(): 解除写锁,会先通知所有阻塞的读操作goroutine,然后才会释放持有的互斥锁。
  1. 为什么写操作不会被饿死?

    这时候张三道友先跳出来问了一句,什么是写操作被饿死?

    这是由于写操作要等待读操作结束后才可以获得锁,而写操作在等待期间可能还有新的读操作持续到来,如果写操作等待所有读操作结束,很可能会一直阻塞,这种现象称之为写操作被饿死。

    通过RWMutex结构体中的readerWait属性可完美解决这个问题

    当写操作到来时,会把RWMutex.readerCount值拷贝到RWMutex.readerWait中,用于标记排在写操作前面的读者个数

    前面的读操作结束后,除了会递减RWMutex.readerCount,还会递减RWMutex.readerWait值,当RWMutex.readerWait值变为0时唤醒写操作。

面试点总结

  • sync.RWMutex读写锁的数据结构?
  • 读写锁如何控制资源并发读写?
  • 连续读操作下,写操作如何保证不被饿死?

后语

如果大家对本文提到的面试技术点有任何问题,都可以在评论区进行回复哈,我们共同学习,一起进步!

关注公众号[简道编程],每天一个后端技术面试点

在这里插入图片描述

标签:面试题,RWMutex,读写,sync,读锁,操作,readerCount
来源: https://blog.csdn.net/xiaodaoge_it/article/details/121580713

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有