如何基于相同字符串上锁?

发布于 2022-09-12 22:28:53 字数 345 浏览 27 评论 0

我有一个方法,接受一个字符串入参,方法会被并发调用,我想在传入相同字符串的调用间上锁,比如有两个线程同时传入"abc"调用该方法,那我希望他们不能同时进入,需等一个完成另一个才进入。与此同时,另一个线程传入"xyz"的调用则不受影响。所以我应该锁什么?

void Foo(string s) {
  lock(what) { } // ???
}

我现在锁的是String.Intern(s),但了解到这样会增加不可回收的驻留字符串,而这个方法在程序运行期间是会被传入无数不同的字符串调用无数次的,所以驻留下来的字符串会很可观,所以我想改进。

求支招,谢谢!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

千秋岁 2022-09-19 22:28:53

好像在内核看到过一个类似问题的解决方案:把字符串哈希到固定数量的桶,每个桶一把锁。

同一个桶里的不同串确实会互相影响,但是根据问题的具体情况可以调整桶数,让冲突的概率降低。

桶里可以有很多串,只要两个不同的串同时需要锁的概率够低就可以。加锁的持续时间越长,冲突可能性就越大。

荆棘i 2022-09-19 22:28:53

考虑过 System.Threading.Mutex 么?这个是互斥锁,并且支持命名锁。

不过是系统级别的,如果你要是程序挂了还没来得及释放锁,不重启系统的话就一直死锁了。但也不是无解,比如加锁前锁的命名把记录下来,程序启动时先尝试执行一次释放。


P.S. 如果不介意引入另一个服务的话,其实用 Redis、Zookeeper 等等来实现分布式锁更好……

西瓜 2022-09-19 22:28:53

MemoryCache + 滑动超时策略是不是你想要的?

亣腦蒛氧 2022-09-19 22:28:53

可以使用ConcurrentDictionary管理锁对象;

ConcurrentDictionary<string,object> lockRing = new ();

...
void Foo(string s) {
lock(lockRing.GetOrAdd(s,key=> new object())){

  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文