从外部同步LinkedHashmap

时间:2012-12-23 23:41:22

标签: java concurrency

在不使用Collections.synchronizedMap的情况下,在外部实现linkedhashmap同步的最佳方法是什么

当使用Collections.synchronizedMap时,整个数据结构被锁定,因此性能受到严重影响。

仅锁定数据结构所需部分的最佳方法是什么。例如如果线程正在访问密钥(K1),它应该只锁定数据结构的Key(K1)和Value(v1)部分

6 个答案:

答案 0 :(得分:3)

您无法从内置的Java实现中获得细粒度锁定的FIFO驱逐并发映射。

查看Guava's Cache或开源ConcurrentLinkedHashMap project

答案 1 :(得分:1)

我想你可能想要同步你所做的后续操作,只是来自地图的值:

Object value = map.get(key);
synchronized(value) {
    doSomethingWith(value);
} 

从Map获取值的同步是有意义的,因为它们可以同时共享和访问;我上面发布的示例应该做你需要的。那应该够了。

顺便说一下,您还可以在执行两个嵌套同步块的键上进行同步:

synchronized(key) {
    Object value = map.get(key);
    synchronized(value) {
        doSomethingWith(value);
    } 
}

密钥 - 通常 - 仅用于访问对象(通过散列)。密钥与哈希值匹配,因此对我来说,通过密钥进行同步并不完全合理。

或者,也许您可​​以继承ConcurrentHashMap,添加LinkedHashMap中缺少的内容。

答案 2 :(得分:1)

Louis Wasserman的建议可能是最好的,因为它为您提供了许多有用的功能。但是,即使你锁定整个地图,你也必须真正地击中它,真的很难让它成为瓶颈(因为你的代码主要是在地图上进行读/写)。如果您不需要Guava Cache的附加功能,则同步地图可能更简单&更好。如果您主要从地图上阅读,也可以使用ReadWriteLock

答案 3 :(得分:0)

如果您不需要LinkedHaspMap,请使用ConcurrentHashMap包中的java.util.concurrent

专为速度和螺纹安全而设计。它使用最小可能的锁定来实现其线程安全性。

答案 4 :(得分:0)

最佳选择是使用java.util.concurrent.ConcurrentHashMap

我看不出如何只能外部锁定zour Map的部分内容,因为你无法控制通过调用任何map函数在内部访问哪些共享数据结构。

答案 5 :(得分:0)

HashMap或LinkedHashMap中的插入可能会导致重新散列,因为它会增加大小和存储区数量之间的比率。让两个或多个线程同时重新进行同步将是一场灾难。

即使您只是在进行get,另一个线程可能正在从同一个存储桶中删除一个条目,因此您正在扫描正在修改的链接列表。您还可以同时将两个或多个线程附加到主链接列表。

如果没有链接,请使用java.util.concurrent.ConcurrentHashMap,如已建议的那样。