|
3 | 3 |
|
4 | 4 | ### ConcurrentMap
|
5 | 5 |
|
6 |
| -`Map` 通常用于高性能服务器应用程序中 - 例如,用作缓存实现 - 因此高吞吐量线程安全的地图实现是 `Java` 平台的重要组成部分。 同步地图(例如由 `Collections.synchronizedMap` 提供的 `Map`)无法满足此要求,因为在完全同步的情况下,每个操作都需要在整个地图上获得排他锁,从而有效地序列化对它的访问。 我们很快就会看到 `ConcurrentHashMap`,可以在吞吐量上获得非常大的增益,只锁定一部分集合。 但是因为客户端没有单独的锁来获得独占访问权限,所以客户端锁定不再起作用,并且客户端需要来自集合本身的帮助来执行原子动作。 |
| 6 | +`Map` 通常用于高性能服务器应用程序中 - 例如,用作缓存实现 - 因此高吞吐量线程安全的 `Map` 实现是 `Java` 平台的重要组成部分。 同步 `Map`(例如由 |
| 7 | +`Collections.synchronizedMap` 提供的 `Map`)无法满足此要求,因为在完全同步的情况下,每个操作都需要在整个地图上获得排他锁,从而有效地序列化对它的访 |
| 8 | +问。 我们很快就会看到 `ConcurrentHashMap`,可以在吞吐量上获得非常大的增益,只锁定一部分集合。 但是因为客户端没有单独的锁来获得独占访问权限,所以客 |
| 9 | +户端锁定不再起作用,并且客户端需要来自集合本身的帮助来执行原子动作。 |
7 | 10 |
|
8 | 11 | 这就是 `ConcurrentMap` 接口的目的。 它为以原子方式执行复合操作的方法提供声明。 有四种方法:
|
9 | 12 |
|
10 | 13 | ```java
|
11 |
| - V putIfAbsent(K key, V value) // 仅当密钥当前不存在时才将密钥与值关联。 如果键存在,则返回旧值(可以为空),否则返回 null |
12 |
| - boolean remove(Object key, Object value) // 只有在当前映射为值的情况下才移除键。 如果该值已删除,则返回 true,否则返回 false |
13 |
| - V replace(K key, V value) // 仅当密钥当前存在时才替换密钥的条目。 如果密钥存在,则返回旧值(可以为 null),否则返回 null |
14 |
| - boolean replace(K key, V oldValue, V newValue) // 只有在当前映射到 oldValue 的情况下才替换键的条目。 如果值被替换则返回 true,否则返回 false |
| 14 | +V putIfAbsent(K key, V value) // 仅当密钥当前不存在时才将密钥与值关联。 如果键存在,则返回旧值(可以为空),否则返回 null |
| 15 | +boolean remove(Object key, Object value) // 只有在当前映射为值的情况下才移除键。 如果该值已删除,则返回 true,否则返回 false |
| 16 | +V replace(K key, V value) // 仅当密钥当前存在时才替换密钥的条目。 如果密钥存在,则返回旧值(可以为 null),否则返回 null |
| 17 | +boolean replace(K key, V oldValue, V newValue) // 只有在当前映射到 oldValue 的情况下才替换键的条目。 如果值被替换则返回 true,否则返回 false |
15 | 18 | ```
|
16 | 19 |
|
17 | 20 | ### ConcurrentHashMap
|
18 | 21 |
|
19 |
| -`ConcurrentHashMap` 提供了 `ConcurrentMap` 的实现,并提供了一个解决吞吐量与线程安全性问题的高效解决方案。 它针对阅读进行了优化,因此即使在更新表时检索也不会被阻止(为此,合同规定检索结果将反映在检索开始之前完成的最新更新操作)。 更新通常也可以不受阻塞地进行,因为 `ConcurrentHashMap` 不是由一个而是由一组表组成,称为段,它们可以独立锁定。 如果段的数量相对于访问表的线程数量足够大,那么每个段的任何时间通常不会有多个更新正在进行。`ConcurrentHashMap` 的构造函数类似于 `HashMap` 的构造函数,但是还有一个额外的提供程序员控制 `Map` 将使用的段数(其并发级别): |
| 22 | +`ConcurrentHashMap` 提供了 `ConcurrentMap` 的实现,并提供了一个解决吞吐量与线程安全性问题的高效解决方案。 它针对阅读进行了优化,因此即使在更新表时 |
| 23 | +检索也不会被阻止(为此,合同规定检索结果将反映在检索开始之前完成的最新更新操作)。 更新通常也可以不受阻塞地进行,因为 `ConcurrentHashMap` 不是由一 |
| 24 | +个而是由一组表组成,称为段,它们可以独立锁定。 如果段的数量相对于访问表的线程数量足够大,那么每个段的任何时间通常不会有多个更新正在进行。 |
| 25 | +`ConcurrentHashMap` 的构造函数类似于 `HashMap` 的构造函数,但是还有一个额外的提供程序员控制 `Map` 将使用的段数(其并发级别): |
20 | 26 |
|
21 | 27 | ```java
|
22 |
| - ConcurrentHashMap() |
23 |
| - ConcurrentHashMap(int initialCapacity) |
24 |
| - ConcurrentHashMap(int initialCapacity, float loadFactor) |
25 |
| - ConcurrentHashMap( |
26 |
| - int initialCapacity, float loadFactor, int concurrencyLevel) |
27 |
| - ConcurrentHashMap(Map<? extends K,? extends V> m) |
| 28 | +ConcurrentHashMap() |
| 29 | +ConcurrentHashMap(int initialCapacity) |
| 30 | +ConcurrentHashMap(int initialCapacity, float loadFactor) |
| 31 | +ConcurrentHashMap( |
| 32 | +int initialCapacity, float loadFactor, int concurrencyLevel) |
| 33 | +ConcurrentHashMap(Map<? extends K,? extends V> m) |
28 | 34 | ```
|
29 | 35 |
|
30 |
| -`ConcurrentHashMap` 类是在任何不需要锁定整个表的应用程序中使用 `Map` 的有用实现;这是 `SynchronizedMap` 的一个不支持的功能。这有时会带来问题:例如,`size` 方法尝试在不使用锁的情况下对地图中的条目进行计数。但是,如果地图正在同时更新,则尺寸方法将无法获得一致的结果。在这种情况下,它通过锁定所有分段获得对地图的独占访问权,从每个分段中获取入口数,然后再次解锁它们。与此相关的性能成本对于常见操作的高度优化性能(尤其是读取)来说是合理的折衷。总体而言,`ConcurrentHashMap` 在高度并发的上下文中是不可或缺的,它比任何可用的替代方法都要好得多。 |
| 36 | +`ConcurrentHashMap` 类是在任何不需要锁定整个表的应用程序中使用 `Map` 的有用实现;这是 `SynchronizedMap` 的一个不支持的功能。这有时会带来问题:例 |
| 37 | +如,`size` 方法尝试在不使用锁的情况下对地图中的条目进行计数。但是,如果地图正在同时更新,则尺寸方法将无法获得一致的结果。在这种情况下,它通过锁定所有 |
| 38 | +分段获得对地图的独占访问权,从每个分段中获取入口数,然后再次解锁它们。与此相关的性能成本对于常见操作的高度优化性能(尤其是读取)来说是合理的折衷。总 |
| 39 | +体而言,`ConcurrentHashMap` 在高度并发的上下文中是不可或缺的,它比任何可用的替代方法都要好得多。 |
31 | 40 |
|
32 | 41 | 忽略刚刚描述的锁定开销,`ConcurrentHashMap` 的操作成本类似于 `HashMap` 的操作成本。集合视图返回弱一致的迭代器。
|
33 | 42 |
|
34 | 43 | 《《《 [下一节](05_ConcurrentNavigableMap.md) <br/>
|
35 |
| -《《《 [返回首页](../README.md) |
| 44 | +《《《 [返回首页](../README.md) |
0 commit comments