[Go WebSocket] 多房间的聊天室(五)用多个小锁代替大锁,提高效率

大家好,我是公众号「线下聚会游戏」作者,开发了《联机桌游合集》,是个网页,可以很方便的跟朋友联机玩斗地主、五子棋等游戏。其中的核心技术就是WebSocket,我会分享如何用Go实现WebSocket服务,文章写在专栏《Go WebSocket》里,关注专栏跟我一起学习吧!

背景

在专栏《Go WebSocket》里,有一些前置文章:

第一篇文章:《为什么我选用Go重构Python版本的WebSocket服务?》,介绍了我的目标。

第二篇文章:《你的第一个Go WebSocket服务: echo server》,介绍了一下怎么写一个WebSocket server。

第三篇文章:《你的第二个Go WebSocket服务: 聊天室》,介绍了如何实现一个单房间的聊天室。

第四篇文章:《你的第三个Go WebSocket服务: 多房间的聊天室(上:思考篇)》,介绍了实现一个多房间的聊天室的思路。

第五篇文章:《你的第三个Go WebSocket服务: 多房间的聊天室(下:实践篇)》,介绍了实现一个多房间的聊天室的代码。

第六篇文章:《你的第三个Go WebSocket服务: 多房间的聊天室(自动清理无人房间)》,介绍了如何清理无人的房间,避免内存无限增长的问题。

第七篇文章:《你的第三个Go WebSocket服务: 多房间的聊天室(黑天鹅事件)》,介绍了如何避免并发导致的资源竞争的问题,是通过悲观锁解决的。

第八篇文章:《基于Go WebSocket手写一个简易版的远程web shell》,介绍了基于Go WebSocket手写一个简单的Web Shell,可以体验直接在浏览器中输入linux命令的感觉~

温馨提示:阅读本文前,需要至少阅读前7篇文章。如果你没阅读前7篇文章,一定要先看一下,因为这篇文章更复杂,如果你不弄懂上面几篇,这篇可能跟不上节奏噢。

扫描二维码关注公众号,回复: 14421448 查看本文章

回顾:register和unregister竞争

上篇文章我们提到,存在黑天鹅事件(小概率事件),register和unregister会竞争资源,导致数据异常。

最终我们通过增加「悲观锁」解决问题。

需要注意的是,我们上文加的锁是一个全局的锁。

这意味着,同时有100个客户端(即使是不同的房间)请求连接时,他们必须排好队,一个一个处理。等上一个请求加锁、释放锁后,才处理下一个请求。不能发挥goroutine并行的优势。

换句话说,这个「锁」太大了!影响了程序运行效率。

怎么解决呢?我们把「锁」拆分成更多小锁,每个房间用一把锁,这就解决了问题。保证可以同时处理「不同的房间的用户连接请求」。

用小锁代替大锁

用「多个小锁」代替「大锁」,可以显著提高各场景下的并行效率。

如下:

main.go

image.png

image.png

client.go

image.png

hub.go

image.png

但是给每个房间加锁,存放在同一个map里,读取这个map有需要引入一个全局锁mutexForRoomMutexes

其实,大可不必担心,现在已经优化了很多了!

因为你可以看到,这个锁释放的非常快,影响不大。但是上篇文章的锁mutex,不仅是全局锁,而且占用时间较长。

源码

github.com/HullQin/go-…

写在最后

我是HullQin,独立开发了《联机桌游合集》,是个网页,可以很方便的跟朋友联机玩斗地主、五子棋等游戏,不收费无广告。还独立开发了《合成大西瓜重制版》。还开发了《Dice Crush》参加Game Jam 2022。喜欢可以关注我噢~我有空了会分享做游戏的相关技术,会在这2个专栏里分享:《教你做小游戏》《极致用户体验》

本文正在参加技术专题18期-聊聊Go语言框架

猜你喜欢

转载自juejin.im/post/7126195335491223582