写点什么

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

作者:HullQin
  • 2022 年 9 月 14 日
    广东
  • 本文字数:1344 字

    阅读完需:约 4 分钟

我是 HullQin,公众号线下聚会游戏的作者(欢迎关注公众号,发送加微信,交个朋友),转发本文前需获得作者 HullQin 授权。我独立开发了《联机桌游合集》,是个网页,可以很方便的跟朋友联机玩斗地主、五子棋等游戏,不收费没广告。还独立开发了《合成大西瓜重制版》。还开发了《Dice Crush》参加 Game Jam 2022。喜欢可以关注我 HullQin 噢~我有空了会分享做游戏的相关技术。

背景

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


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


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


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


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


第五篇文章:《多房间的聊天室(二)代码实现》,介绍了实现一个多房间的聊天室的代码。


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


第七篇文章:《多房间的聊天室(三)自动清理无人房间》,介绍了如何避免并发导致的资源竞争的问题,是通过悲观锁解决的。


第八篇文章:《多房间的聊天室(三)自动清理无人房间》,介绍了基于 Go WebSocket 手写一个简单的 Web Shell,可以体验直接在浏览器中输入 linux 命令的感觉~


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

回顾:register 和 unregister 竞争

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


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


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


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


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


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

用小锁代替大锁

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


如下:


main.go




client.go



hub.go



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


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


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

源码

仓库地址:github.com/HullQin/go-websocket-examples


关注这个 commit:github.com/HullQin/go-websocket-examples/commit/b12271a9531360d407c22c54c854e177e7e48fda

写在最后

我是 HullQin,公众号线下聚会游戏的作者(欢迎关注公众号,发送加微信,交个朋友),转发本文前需获得作者 HullQin 授权。我独立开发了《联机桌游合集》,是个网页,可以很方便的跟朋友联机玩斗地主、五子棋等游戏,不收费没广告。还独立开发了《合成大西瓜重制版》。还开发了《Dice Crush》参加 Game Jam 2022。喜欢可以关注我 HullQin 噢~我有空了会分享做游戏的相关技术。

发布于: 刚刚阅读数: 5
用户头像

HullQin

关注

公众号【线下聚会游戏】 2020.10.07 加入

game.hullqin.cn 我做了一些联机桌游网页:支持2-10人联机的UNO、2-4人联机的斗地主、2人联机的五子棋。无需下载,点开即玩!叫上朋友,即刻开局!不看广告,不做任务,享受「纯粹」的游戏!

评论

发布
暂无评论
[Go WebSocket] 多房间的聊天室(五)用多个小锁代替大锁,提高效率_Go_HullQin_InfoQ写作社区