当前位置:网站首页>golang中的读写锁原理
golang中的读写锁原理
2022-07-16 14:22:00 【raoxiaoya】
读写锁特点
- 读+读:通过
- 读+写:阻塞
- 写+读:阻塞
- 写+写:阻塞
type RWMutex struct {
w Mutex // held if there are pending writers
writerSem uint32 // 控制获取写锁的信号量
readerSem uint32 // 控制获取读锁的信号量
readerCount int32
readerWait int32
}
func (rw *RWMutex) RLock() {
if atomic.AddInt32(&rw.readerCount, 1) < 0 {
runtime_SemacquireMutex(&rw.readerSem, false, 0)
}
}
func (rw *RWMutex) RUnlock() {
if r := atomic.AddInt32(&rw.readerCount, -1); r < 0 {
rw.rUnlockSlow(r)
}
}
func (rw *RWMutex) rUnlockSlow(r int32) {
if r+1 == 0 || r+1 == -rwmutexMaxReaders {
throw("sync: RUnlock of unlocked RWMutex")
}
// 每次释放读锁,readerWait 都会减1,直到为0就释放 writerSem 信号量
if atomic.AddInt32(&rw.readerWait, -1) == 0 {
runtime_Semrelease(&rw.writerSem, false, 1)
}
}
func (rw *RWMutex) Lock() {
rw.w.Lock()
// r 就是 readerCount 原先的值
// readerCount 减去一个很大的值,就是表明写锁已经加上了,后续的读锁请求将阻塞
r := atomic.AddInt32(&rw.readerCount, -rwmutexMaxReaders) + rwmutexMaxReaders
// 获取了写锁,还要等待所以的读锁全部释放
// readerWait + r 其实就是还有多少个读锁没有释放,
// 如果不为0,则需要等待信号量
// 如果为0,则直接成功,不能等待信号量
if r != 0 && atomic.AddInt32(&rw.readerWait, r) != 0 {
runtime_SemacquireMutex(&rw.writerSem, false, 0)
}
}
func (rw *RWMutex) Unlock() {
// 将 readerCount 恢复正常值,也就是读锁的个数
r := atomic.AddInt32(&rw.readerCount, rwmutexMaxReaders)
if r >= rwmutexMaxReaders {
throw("sync: Unlock of unlocked RWMutex")
}
// 向所以的读锁释放信号量
for i := 0; i < int(r); i++ {
runtime_Semrelease(&rw.readerSem, false, 0)
}
rw.w.Unlock()
}
首先是获取读锁和释放读锁,在不考虑其他的情况下,直接加减readerCount即可。
获取写锁的过程是互斥的,因此需要一个互斥锁来加持;拿到了互斥锁之后,就意味着抢到了写锁,如果此时已经有协程在使用读锁,那么需要等到这些读锁全部释放,对应的信号量为writerSem。
读写锁的关键是,既要操作信号量,但是有可能根本就没有对方,所以又不能盲目的操作,所以先判断一个数量,然后再操作。
边栏推荐
猜你喜欢

C#网络应用编程,实验4:线程管理练习

勤于奋闲聊
![LeetCode 剑指Offer II 041滑动窗口的平均值[滑动窗口] HERODING的LeetCode之路](/img/29/ea4b91cc90ca0dd0eea7e6a3d33394.png)
LeetCode 剑指Offer II 041滑动窗口的平均值[滑动窗口] HERODING的LeetCode之路

MySQL super detailed installation tutorial will teach you to install Mysql to use the simplest MySQL installation method of MySQL. This method is also simple to install and uninstall

一文详解图像中的无监督学习

Error ora-01017 is reported after RMAN recovers

MyQL数据库突然不见了,该如何进行恢复?

Leetcode 49. 字母异位词分组

动态内存管理(C语言)详细总结

C#网络应用编程,异步编程基础练习
随机推荐
STL string
标准输入输出流
New exploration of Ali mother's display advertising engine: towards the overall optimal allocation of computing power
C#求完全数,输出水仙花以及类的使用
【C语言进阶】⑨动态内存分配知识总结 超详细
uCOS-iii学习笔记(11)——任务信号量和任务消息队列
Halcon and C # detect surface defects - ROI interaction (III) (functions such as synchronous scaling and clipping with pictures)
nn. BCEWithLogisticLoss() & nn. The difference between bceloss(), nn CrossEntropyLoss() & nn. Nllloss() differences
Cloud native (XXXV) | Prometheus introduction and installation
Pytoch build network details summary
HALCON联合C#检测表面缺陷——ROI交互(三)(和图片同步缩放裁剪等功能)
华为影像XMAGE:求尽世间像,终见菩提心
【C#】正序、逆序、最大值、最小值和平均值
监听拖拽事件,第一次拖拽得不到上传的文件内容,第二次以后就能正常得到上传的文件内容
程序分析与优化 - 11 多分支分析
July training (day 16) - queue
STL string
深圳某游戏研发公司给每个工位都装监控,网友:堪比坐牢!
[基础服务] [数据库] MySQL 主从复制部署与配置
MyQL数据库突然不见了,该如何进行恢复?