[Go WebSocket] 多房间的聊天室(六)为什么要加锁?不加锁行不行啊?

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

背景

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

《单房间的聊天室》,介绍了如何实现一个单房间的聊天室。

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

《多房间的聊天室(二)代码实现》,介绍了实现一个多房间的聊天室的代码。

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

《多房间的聊天室(四)黑天鹅事件》,介绍了如何避免并发导致的资源竞争的问题,是通过悲观锁解决的。

《多房间的聊天室(五)用多个小锁代替大锁,提高效率》,介绍了通过把一个全局大锁拆分成多个小锁,提高了并发效率。

温馨提示:阅读本文前,最好阅读下上面的文章。因为这篇文章更复杂,如果你不弄懂上面几篇,这篇可能跟不上节奏噢。

本文回答以下问题:

为什么一定要加锁?加锁后,你的代码逻辑是对的吗?

换个描述方法,本文是论证了给代码逻辑加锁的 必要性充分性

思路

论证必要性

我们只要把加锁相关代码删掉,模拟真实环境发高并发的请求,测试是否有bug出现。一旦出现bug,就认为加锁是必要的。

论证充分性

我们把锁的代码加上,模拟真实环境发高并发的请求,测试bug是否修复。并且认为修改代码,增加延时,扩大bug出现可能性。如果最终没有任何bug,表明现在服务器代码逻辑是正确的。

分析验证的目标

如果把代码里没有锁,会有什么问题?

我们把锁相关代码注释掉,分析下代码:

1.png

建立连接时,我们根据roomId,从house中获取了room。

但是goroutine随时有可能主动让出执行权,去执行其它goroutine。而且我们知道,这个r.HandleFunc()里的函数,是每有一个客户端请求连接时,都是一个新的goroutine。

如果同时有多个客户端请求连接同一个房间,他们都刚好在room, ok := house[roomId]后,让出了执行权,那么他们都发现该房间都不存在,各自建立了新房间,导致他们虽然房间号相同,但是房间不同,无法相互通信。

怎么测试这个场景呢?

我们同时在客户端启动多个WebSocket连同一个房间即可(假设启动10个连接),然后等所有客户端连接完毕后,各自发一个消息,看看每个客户端收到了多少消息。

在同一个房间里,有10个人进来了,每人发了1个广播消息,这个消息应该会广播给10个人。有10个人发了消息,所以预期每个人会收到10个消息。一共就是100条消息。

但是如果Bug发生,应该是少于100条消息的,我们验证一下!

开发测试脚本

因为我们提供的WebSocket服务的客户端是在浏览器中,所以,为了模拟生产环境,我们的测试脚本也用htmljs开发。

因为是高并发,所以一个页面可以开启多个WebSocket连接,通过输入参数,可以调整房间数目、每个房间的客户端的数目。

交互如下:

2.png

代码如下:

<body>
<div>
  <label>
    Number of rooms: <input type="number" id="rooms" value="1">
  </label>
</div>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hull Qin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值