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

我是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

1.png

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

client.go

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

hub.go

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

但是给每个房间加锁,存放在同一个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 噢~我有空了会分享做游戏的相关技术。

你可能感兴趣的:(后端gohtml5程序员)