这个问题问得好,但实际应该不会出现。
用户想修改微信号 wxid_0为 wxid_1,要查询数据库中是否已存在 wxid_1,在查询的过程中,肯定会上锁,不让修改数据库,不然可以出现有多个用户查询没有,然后并发修改成 wxid_1 的情况。这是悲观锁(pessimistic lock)。一个个的排队修改就出现了千军万马过独木桥的情形,这样就太慢了。
怎么办?可以修改锁的粒度(lock granularity)嘛。比如张三想修改A0为B1,李四想修改C2为D3(微信要求必须以字母开头)。批量提交的数据,A0改为B1的请求提交到 pair<A, B> 池子里,C2改为D3的请求提交到pair<C, D> 池子里,每个池子一把锁,相互独立,于是就可以并行操作了。如果张三和李四心有灵犀,恰恰想到了同一个没被使用的好名,拒绝掉后到的提交请求就可以。
思想熟悉吗?熟悉。快去看一看Java的 java/util/concurrent/CocurrentHashMap.java 的实现吧。为什么会有 CocurrentHashMap?从 HashMap 到CocurrentHashMap 经历了什么?
上面用的首字母当作hash桶。有兴趣的,可以熟悉一下Linus大神写的Git工具,用的头两个字符作为hash桶。目前Git用SHA-1算法,生成40个十六进制的字符。每一次代码提交的hash值,在隐藏目录 .git 下都有记录,其中 .git/objects/ 里都是2个字符的文件夹,文件夹里是38个字符的文件。2+38=40 刚好是一串hash值,对应某一次的提交。
考虑最坏的情形,环形修改——A想修改为B的名,B想修改为C的名,C想修改为D的名,……,Z想修改为A的名(类似操作系统的死锁条件:环状等待)。这种出现的概率极低。处理这种情况,必须封装成原子操作(atomic operation),要么都修改成功,要么都修改失败。处理简单的A/B之间交换名称还好处理(有两个微信号的用户,想不想测试一下交换?目前需要一年后才能再次换回来),太长的环,很可能就放弃处理了,直接返回失败,微信号已存在。
另,降低并发修改的方案可以参考:
具体降低并发修改的措施:
本站所有内容均为互联网搜索引擎提供的公开搜索信息,本站不存储任何数据与内容,任何内容与数据均与本站无关,如有需要请联系相关搜索引擎包括但不限于百度,google,bing,sogou 等
© 2025 tinynews.org All Rights Reserved. 百科问答小站 版权所有