5

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

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

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

4

6 回答 6

3

您无法从内置 Java 实现中获得细粒度锁定、FIFO-eviction 并发映射。

查看GuavaCache或开源ConcurrentLinkedHashMap项目

于 2012-12-24T01:45:30.743 回答
1

Louis Wasserman 的建议可能是最好的,因为它为您提供了很多有用的功能。然而,即使你锁定了整个地图,你也必须非常非常努力地让它成为瓶颈(例如,你的代码主要是在地图上进行读/写)。如果您不需要 Guava 的附加功能Cache,同步地图可能更简单、更好。ReadWriteLock如果您主要从地图上阅读,您也可以使用 a 。

于 2012-12-24T02:15:25.740 回答
1

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

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

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

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

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

密钥 - 通常 - 仅用于访问对象(通过散列)。键由哈希值匹配,因此对我来说同步键没有意义。

或者,也许您可​​以子类ConcurrentHashMap添加LinkedHashMap.

于 2012-12-23T23:49:22.853 回答
0

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

它专为速度和线程安全而设计。它使用尽可能少的锁定来实现其线程安全。

于 2012-12-23T23:51:19.553 回答
0

最好的选择是使用java.util.concurrent.ConcurrentHashMap.

我看不出如何仅从外部锁定 zour Map 的一部分,因为您无法通过调用任何 maps 函数来控制内部访问哪些共享数据结构。

于 2012-12-23T23:52:53.837 回答
0

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

即使你只是在做一个获取,另一个线程可能会从同一个桶中删除一个条目,所以你正在扫描一个正在你下面修改的链表。您还可以同时将两个或多个线程附加到主链表。

如果您可以不使用链接,请使用 java.util.concurrent.ConcurrentHashMap,如前所述。

于 2012-12-24T00:00:35.840 回答