架构师_程序员

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2180|回复: 1

[资料] .net/c# 用户多线程并发lock(string){...}详解

[复制链接]
发表于 2019-7-3 15:25:19 | 显示全部楼层
常见误用场景:在订单支付环节中,为了防止用户不小心多次点击支付按钮而导致的订单重复支付问题,我们用 lock(订单号) 来保证对该订单的操作同时只允许一个线程执行。

这样的想法很好,至少比 lock(处理类的private static object)要好,因为lock订单号想要的效果是只锁当前1个订单的操作,而如果lock静态变量,那就是锁所有的订单,就会导致所有的订单进行排队,这显然是不合理的。

那么本文开篇说的lock(订单号)的做法可以实现想要的效果吗?我们先用一些代码来还原使用场景。

如果忽略用户信息及其他验证,那代码差不多是这样:
这样的代码看起来好像没有什么问题,对于lock关键字,MSDN上面包括能够百度到的资料,好像都是说建议不要使用lock(string),而原因都是同一个。以下这段话摘自MSDN关于lock字符串的建议:

由于进程中使用同一字符串的任何其他代码将共享同一个锁,所以出现 lock(“myLock”) 问题。
这句话隐藏了一个巨大的机关,那就是“同一字符串”。

什么叫“同一字符串”?请看代码:


请问上面的str1和str2是同一字符串吗?答案是YES。

再看:


上面的str1和str2还是同一字符串吗?答案就是NO了。

好了,再回到我们订单支付的问题上面来。在我们的代码中, lock(orderNumber) ,当用户手滑一不小心多点了几次,请问每次进入这个action的orderNumber是同一字符串吗?答案是NO。这就是说

上面处理订单的代码实际上并没有起到任何lock的作用。

实际上,字符串比较分两种,请看代码:


上面的代码第一行输出True,第二行输出False。相信不用我解释你也明白MSDN所说的“同一字符串”了。

最佳解决方案

最佳锁定字符串的解决方案:



QQ截图20190703150234.jpg

demo代码:




在网站中,有时候可能用到全局变量,这个全局变量,在多用户并发访问的时候,可能会出现异常,这时,我们会设置一个全局的锁,但是,这样的弊端是,所有访问都会依次等待。

有些场景,例如:同一个用户15秒内只能评论一次,如果用全局锁的话,在用户激增的时候,评论功能处理会非常慢,非常影响用户体验。

这时,我们可以对每个用户单独设置锁,lock(string){...},锁的名称可以定义为:方法名+用户的id,这样实现了每个用户有独立的锁,在判断评论间隔时间的时候,不会影响到其它用户评论。

(完)




上一篇:MFC的LPSTR类型写法
下一篇:openssl明明已经更新了,apache还是提示使用的旧版?
码农网,只发表在实践过程中,遇到的技术难题,不误导他人。
发表于 2019-7-3 20:02:32 | 显示全部楼层
这是好东西
码农网,只发表在实践过程中,遇到的技术难题,不误导他人。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

免责声明:
码农网所发布的一切软件、编程资料或者文章仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。

Mail To:help@itsvse.com

QQ|Archiver|手机版|小黑屋|架构师 ( 鲁ICP备14021824号-2 )|网站地图

GMT+8, 2020-7-11 23:03

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表