简体   繁体   English

Java:使用ConcurrentHashMap作为锁管理器

[英]Java: Using ConcurrentHashMap as a lock manager

I'm writing a highly concurrent application, needing access to a large fine-grained set of shared resources. 我正在编写一个高度并发的应用程序,需要访问一大组细粒度的共享资源。 I'm currently writing a global lock manager to organize this. 我目前正在编写一个全局锁管理器来组织此操作。 I'm wondering if I can piggyback off the standard ConcurrentHashMap and use that to handle the locking? 我想知道是否可以附带标准ConcurrentHashMap并使用它来处理锁定? I'm thinking of a system like the following: 我在考虑以下系统:

  • A single global ConcurrentHashMap object contains a mapping between the unique string id of the resource, and a 单个全局ConcurrentHashMap对象包含资源的唯一字符串ID与 lock protecting that resource 锁定保护该资源 unique id of the thread using the resource 使用资源的线程的唯一ID
  • Tune the concurrency factor to reflect the need for a high level of concurrency 调整并发因子以反映对高并发水平的需求
  • Locks are acquired using the atomic conditional replace(K key, V oldValue, V newValue) method in the hashmap 使用哈希图中的原子条件replace(K key, V oldValue, V newValue)方法获取锁。
  • To prevent lock contention when locking multiple resources, locks must be acquired in alphabetical order 为防止在锁定多个资源时发生锁争用,必须按字母顺序获取锁

Are there any major issues with the setup? 设置是否存在重大问题? How will the performance be? 表现如何?

I know this is probably going to be much slower and more memory-heavy than a properly written locking system, but I'd rather not spend days trying to write my own, especially given that I probably won't be able to match Java's professionally-written concurrency code implementing the map. 我知道这可能会比正确编写的锁定系统要慢得多,而且会占用更多的内存,但是我宁愿不花几天时间尝试编写自己的锁定系统,尤其是考虑到我可能无法与Java专业人士相提并论并发代码实现地图。

Also, I've never used ConcurrentHashMap in a high-load situation, so I'm interested in the following: 另外,我从未在高负载情况下使用ConcurrentHashMap,因此我对以下内容感兴趣:

  • How well will this scale to large numbers of elements? 它将如何适应大量元素? (I'm looking at ~1,000,000 being a good cap. If I reach beyond that I'd be willing to rewrite this more efficiently) (我认为〜1,000,000是一个好的上限。如果我能达到这个上限,我将更有效地重写它)
  • The documentation states that re-sizing is "relatively" slow. 该文档指出,重新调整大小“相对”缓慢。 Just how slow is it? 到底有多慢? I'll probably have to re-size the map once every minute or so. 我可能不得不每分钟左右更改地图大小。 Is this going to be problematic with the size of map I'm looking at? 这与我正在查看的地图大小有关吗?

Edit: Thanks Holger for pointing out that HashMaps shouldn't have that big of an issue with scaling 编辑:感谢Holger指出HashMaps在缩放方面不应该有那么大的问题

Also, is there is a better/more standard method out there? 另外,有没有更好/更标准的方法呢? I can't find any places where a system like this is used, so I'm guessing that either I'm not seeing a major flaw, or theres something else. 我找不到使用这种系统的任何地方,所以我猜我可能没有发现重大缺陷,或者还有其他问题。


Edit: 编辑:

The application I'm writing is a network service, handling a variable number of requests. 我正在编写的应用程序是一个网络服务,处理可变数量的请求。 I'm using the Grizzly project to balance the requests among multiple threads. 我正在使用Grizzly项目在多个线程之间平衡请求。 Each request uses a small number of the shared resources (~30), so in general, I do not expect a large great deal of contention. 每个请求都使用少量的共享资源(约30个),因此,一般而言,我不希望有太多争用。 The requests usually finish working with the resources in under 500ms. 这些请求通常在500毫秒内完成使用资源的工作。 Thus, I'd be fine with a bit of blocking/continuous polling, as the requests aren't extremely time-sensitive and contention should be minimal. 因此,我对一些阻塞/连续轮询没什么问题,因为请求不是非常时间敏感的,因此争用应该最少。

In general, seeing that a proper solution would be quite similar to how ConcurrentHashMap works behind the scenes, I'm wondering if I can safely use that as a shortcut instead of writing/debugging/testing my own version. 通常,看到合适的解决方案与ConcurrentHashMap在后台工作的方式非常相似,我想知道是否可以安全地将其用作快捷方式,而不是编写/调试/测试自己的版本。

The re-sizing issue is not relevant as you already told an estimate of the number of elements in your question. 调整大小的问题无关紧要,因为您已经对问题中的元素数量进行了估算。 So you can give a ConcurrentHashMap an initial capacity large enough to avoid any rehashing. 因此,您可以为ConcurrentHashMap提供足够大的初始容量,以避免任何重新哈希。

The performance will not depend on the number of elements, that's the main goal of hashing, but the number of concurrent threads. 性能不会取决于元素的数量,这是哈希的主要目标,而是并发线程的数量。

The main problem is that you don't have a plan of how to handle failed locks. 主要问题是您没有如何处理失败的锁的计划。 Unless you want to poll until locking succeeds (which is not recommended) you need a way of putting a thread to sleep which implies that the thread currently owning the lock has to wake up a sleeping thread on release if one exists. 除非要轮询直到锁定成功(不建议这样做),否则您需要一种使线程进入睡眠状态的方法,这意味着当前拥有锁的线程必须在释放线程时唤醒睡眠线程(如果存在)。 So you end up requiring conventional Lock features a ConcurrentHashMap does not offer. 因此,您最终需要使用ConcurrentHashMap不提供的常规Lock功能。

Creating a Lock per element (as you said ~1,000,000) would not be a solution. 为每个元素创建一个Lock (如您所说的〜1,000,000)不是解决方案。


A solution would look a bit like the ConcurrentHashMap works internally. 解决方案看起来有点像ConcurrentHashMap在内部工作。 Given a certain concurrency level, ie the number of threads you might have (rounded up), you create that number of Lock s (which would be a far smaller number than 1,000,000). 给定一定的并发级别,即您可能具有的线程数量(向上舍入),则创建该数量的Lock (比1,000,000小得多)。

Now you assign each element one of the Lock s. 现在,您为每个元素分配一个Lock A simple assignment would be based on the element's hashCode , assuming it is stable. 假设它是稳定的,则将基于该元素的hashCode进行简单分配。 Then locking an element means locking the assigned Lock which gives you up to the configured concurrency level if all currently locked elements are mapped to different Lock s. 然后锁定元素意味着锁定分配的Lock ,如果所有当前锁定的元素都映射到不同的LockLock可以使您达到配置的并发级别。

This might imply that threads locking different elements block each other if the elements are mapped to the same Lock , but with a predictable likelihood. 这可能意味着,如果将不同元素锁定到相同的Lock ,则锁定不同元素的线程会互相阻塞,但是可能性是可预测的。 You can try fine-tuning the concurrency level (as said, use a number higher than the number of threads) to find the best trade-off. 您可以尝试微调并发级别(如前所述,使用比线程数高的数字)来找到最佳的权衡。

A big advantage of this approach is that you do not need to maintain a data structure that depends on the number of elements. 这种方法的一大优势是您不需要维护依赖于元素数量的数据结构。 Afaik, the new parallel ClassLoader uses a similar technique. Afaik,新的并行ClassLoader使用了类似的技术。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM