[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"article-hashmap-shibushixianchenganquanderuguorangnilaishixianyigexianchenganquande-hashmap-niyaozenmeshejiruguobuyongjiasuoniyaozenmesheji":3},{"id":4,"title":5,"slug":6,"summary":7,"content":8,"contentHtml":9,"wordCount":10,"readingTime":11,"categoryId":12,"tags":13,"coverImage":13,"thumbnail":13,"status":14,"isTop":15,"isRecommended":15,"allowComments":15,"password":13,"viewCount":16,"likeCount":15,"commentCount":15,"seoTitle":5,"seoKeywords":17,"seoDescription":18,"source":13,"sourceUrl":13,"publishTime":19},"2010914302024806401","HashMap 是不是线程安全的？如果让你来实现一个线程安全的 HashMap 你要怎么设计？如果不用加锁你要怎么设计？","hashmap-shibushixianchenganquanderuguorangnilaishixianyigexianchenganquande-hashmap-niyaozenmeshejiruguobuyongjiasuoniyaozenmesheji","HashMap 的线程安全性是多线程编程中的一个重要问题，下面我将为你详细解答，并探讨线程安全 HashMap 的设计方案。 # 🔒 HashMap 的线程安全性分析 ## HashMap 的非线程安全本质 HashMap 在设计上**不是线程安全**的。当多个线程同时访问和修改同一个 HashMap 实例时，会导致不可预知的行为。 ### 并发环境下的主要问题： - **数据竞争**：多个线程同时执行 put\u002Fremove 操作可能导致数据丢失或覆盖 - **死循环**：在扩容过程中，多线程可能导致链表形成环，引发 CPU 100% 问题 - **大小不一致**：size() 方法返回的结果可能不准确 ### 特例分析 需要注意的是，当 HashMap 作为**方法内的局部变量**，且每个线程拥有独立实例时，不存在线程安全问题。 # 🛠️ 实现线程安全 HashMap 的设计方案 #...","HashMap 的线程安全性是多线程编程中的一个重要问题，下面我将为你详细解答，并探讨线程安全 HashMap 的设计方案。\n\n# 🔒 HashMap 的线程安全性分析\n\n## HashMap 的非线程安全本质\nHashMap 在设计上**不是线程安全**的。当多个线程同时访问和修改同一个 HashMap 实例时，会导致不可预知的行为。\n\n### 并发环境下的主要问题：\n- **数据竞争**：多个线程同时执行 put\u002Fremove 操作可能导致数据丢失或覆盖\n- **死循环**：在扩容过程中，多线程可能导致链表形成环，引发 CPU 100% 问题\n- **大小不一致**：size() 方法返回的结果可能不准确\n\n### 特例分析\n需要注意的是，当 HashMap 作为**方法内的局部变量**，且每个线程拥有独立实例时，不存在线程安全问题。\n\n# 🛠️ 实现线程安全 HashMap 的设计方案\n\n## 1. 基于锁的线程安全方案\n\n### 方案一：全局锁机制\n```java\npublic class SynchronizedHashMap\u003CK, V> {\n    private final HashMap\u003CK, V> map = new HashMap\u003C>();\n    private final Object lock = new Object();\n    \n    public void put(K key, V value) {\n        synchronized(lock) {\n            map.put(key, value);\n        }\n    }\n    \n    public V get(K key) {\n        synchronized(lock) {\n            return map.get(key);\n        }\n    }\n}\n```\n**缺点**：性能较差，同一时间只能有一个线程访问。\n\n### 方案二：读写锁优化\n```java\npublic class ReadWriteLockHashMap\u003CK, V> {\n    private final HashMap\u003CK, V> map = new HashMap\u003C>();\n    private final ReadWriteLock rwLock = new ReentrantReadWriteLock();\n    \n    public V get(K key) {\n        rwLock.readLock().lock();\n        try {\n            return map.get(key);\n        } finally {\n            rwLock.readLock().unlock();\n        }\n    }\n    \n    public void put(K key, V value) {\n        rwLock.writeLock().lock();\n        try {\n            map.put(key, value);\n        } finally {\n            rwLock.writeLock().unlock();\n        }\n    }\n}\n```\n**优势**：允许多个读线程并发访问，提高读密集型应用性能。\n\n## 2. 分段锁设计（JDK7 ConcurrentHashMap 方案）\n\n分段锁将整个哈希表分成多个独立的段（Segment），每个段有自己的锁。\n\n**核心设计**：\n- 默认 16 个段，可并行访问不同段的数据\n- 段内操作才需要获取锁\n- 显著降低锁竞争概率\n\n```java\n\u002F\u002F 简化的分段锁实现概念\npublic class SegmentedHashMap\u003CK, V> {\n    private final Segment\u003CK, V>[] segments;\n    private static final int SEGMENT_COUNT = 16;\n    \n    static class Segment\u003CK, V> extends ReentrantLock {\n        private HashMap\u003CK, V> map = new HashMap\u003C>();\n    }\n    \n    public V get(K key) {\n        int segmentIndex = hash(key) & (SEGMENT_COUNT - 1);\n        Segment\u003CK, V> segment = segments[segmentIndex];\n        segment.lock();\n        try {\n            return segment.map.get(key);\n        } finally {\n            segment.unlock();\n        }\n    }\n}\n```\n\n## 3. JDK8+ ConcurrentHashMap 的进化\n\nJDK8 的 ConcurrentHashMap 放弃了分段锁，采用更精细的锁机制：\n\n### 核心技术：\n- **Node + synchronized + CAS**\n- **链表转红黑树**（当链表长度 ≥ 8）\n- **多线程协同扩容**\n\n### 锁粒度优化：\n从分段锁（锁定多个桶）细化到**桶级别锁**（只锁定单个链表\u002F树的头节点）。\n\n# ⚡ 无锁线程安全 HashMap 设计方案\n\n## 1. CAS（Compare-And-Swap）基础\n\nCAS 是无锁算法的核心，通过硬件保证操作的原子性：\n\n```java\npublic class AtomicExample {\n    private AtomicInteger value = new AtomicInteger(0);\n    \n    public void increment() {\n        int oldValue, newValue;\n        do {\n            oldValue = value.get();\n            newValue = oldValue + 1;\n        } while (!value.compareAndSet(oldValue, newValue));\n    }\n}\n```\n\n## 2. 无锁 HashMap 关键技术\n\n### 原子引用数组\n```java\npublic class LockFreeHashMap\u003CK, V> {\n    private final AtomicReference\u003CNode\u003CK, V>[]> table;\n    \n    public V get(K key) {\n        \u002F\u002F 无锁读取：依赖 volatile 内存语义\n        int index = hash(key) & (table.length() - 1);\n        Node\u003CK, V> node = table.get(index);\n        while (node != null) {\n            if (node.key.equals(key)) return node.value;\n            node = node.next;\n        }\n        return null;\n    }\n}\n```\n\n### 无锁插入实现要点：\n1. **原子查找定位**：使用 CAS 保证查找-插入的原子性\n2. **无锁链表管理**：通过原子引用实现链表操作\n3. **智能排序策略**：节点按特定规则排序，简化 rehash\n\n## 3. 应对 rehash 挑战\n\nrehash 是无锁 HashMap 的最大技术难点，解决方案：\n\n### 惰性 rehash 策略\n- 不立即移动所有节点\n- 在访问时逐步迁移\n- 使用转发节点标记正在迁移的桶\n\n### 一致性哈希技巧\n通过特殊的哈希位反转排序，使节点在 rehash 时保持相对顺序，避免数据移动。\n\n# 📊 方案对比与选择指南\n\n下表总结了不同方案的特性对比：\n\n| 方案 | 线程安全 | 性能 | 实现复杂度 | 适用场景 |\n|------|----------|------|------------|----------|\n| 全局锁 | ✅ | 低 | 简单 | 低并发，简单应用 |\n| 读写锁 | ✅ | 中 | 中等 | 读多写少 |\n| 分段锁 | ✅ | 中高 | 复杂 | 中等并发 |\n| ConcurrentHashMap | ✅ | 高 | 极复杂 | 高并发生产环境 |\n| 无锁实现 | ✅ | 极高 | 极其复杂 | 极限性能需求 |\n\n# 💡 实践建议\n\n1. **优先使用 ConcurrentHashMap**\n   对于大多数应用场景，JDK 提供的 ConcurrentHashMap 是最佳选择。\n\n2. **谨慎考虑自定义无锁实现**\n   - 无锁编程极其复杂，容易出错\n   - 需要深入的并发知识和严格的测试\n   - 仅在性能瓶颈明确且 ConcurrentHashMap 无法满足时考虑\n\n3. **原子操作的合理使用**\n   ```java\n   \u002F\u002F 使用内置原子方法，避免手动同步\n   concurrentMap.compute(\"key\", (k, v) -> v == null ? 1 : v + 1);\n   ```\n\n# 💎 总结\n\nHashMap 确实是非线程安全的，在多线程环境下必须使用同步机制。从简单的全局锁到精细的分段锁，再到复杂的无锁实现，各种方案在性能与复杂度之间有不同的权衡。对于绝大多数实际项目，推荐使用 JDK 提供的 ConcurrentHashMap，它经过了充分测试和优化，能够满足高并发场景的需求。\n\n希望这份详细的解答能帮助你更好地理解 HashMap 的线程安全问题和解决方案！如果你有特定场景的需求，我可以提供更具体的设计建议。","\u003Cp data-line=\"0\">HashMap 的线程安全性是多线程编程中的一个重要问题，下面我将为你详细解答，并探讨线程安全 HashMap 的设计方案。\u003C\u002Fp>\n\u003Ch1 data-line=\"2\" id=\"🔒 HashMap 的线程安全性分析\">🔒 HashMap 的线程安全性分析\u003C\u002Fh1>\n\u003Ch2 data-line=\"4\" id=\"HashMap 的非线程安全本质\">HashMap 的非线程安全本质\u003C\u002Fh2>\n\u003Cp data-line=\"5\">HashMap 在设计上\u003Cstrong>不是线程安全\u003C\u002Fstrong>的。当多个线程同时访问和修改同一个 HashMap 实例时，会导致不可预知的行为。\u003C\u002Fp>\n\u003Ch3 data-line=\"7\" id=\"并发环境下的主要问题：\">并发环境下的主要问题：\u003C\u002Fh3>\n\u003Cul data-line=\"8\">\n\u003Cli data-line=\"8\">\u003Cstrong>数据竞争\u003C\u002Fstrong>：多个线程同时执行 put\u002Fremove 操作可能导致数据丢失或覆盖\u003C\u002Fli>\n\u003Cli data-line=\"9\">\u003Cstrong>死循环\u003C\u002Fstrong>：在扩容过程中，多线程可能导致链表形成环，引发 CPU 100% 问题\u003C\u002Fli>\n\u003Cli data-line=\"10\">\u003Cstrong>大小不一致\u003C\u002Fstrong>：size() 方法返回的结果可能不准确\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch3 data-line=\"12\" id=\"特例分析\">特例分析\u003C\u002Fh3>\n\u003Cp data-line=\"13\">需要注意的是，当 HashMap 作为\u003Cstrong>方法内的局部变量\u003C\u002Fstrong>，且每个线程拥有独立实例时，不存在线程安全问题。\u003C\u002Fp>\n\u003Ch1 data-line=\"15\" id=\"🛠️ 实现线程安全 HashMap 的设计方案\">🛠️ 实现线程安全 HashMap 的设计方案\u003C\u002Fh1>\n\u003Ch2 data-line=\"17\" id=\"1. 基于锁的线程安全方案\">1. 基于锁的线程安全方案\u003C\u002Fh2>\n\u003Ch3 data-line=\"19\" id=\"方案一：全局锁机制\">方案一：全局锁机制\u003C\u002Fh3>\n\n        \u003Cdetails  data-line=\"20\" class=\"md-editor-code\" open=\"\">\n          \u003Csummary class=\"md-editor-code-head\">\n            \u003Cdiv class=\"md-editor-code-flag\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fdiv>\n            \u003Cdiv class=\"md-editor-code-action\">\n              \u003Cspan class=\"md-editor-code-lang\">java\u003C\u002Fspan>\n              \u003Cspan class=\"md-editor-copy-button\" data-tips=\"复制代码\">复制代码\u003C\u002Fspan>\n              \n              \u003Cspan class=\"md-editor-collapse-tips\">\u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"lucide lucide-circle-chevron-left md-editor-icon\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"10\"\u002F>\u003Cpath d=\"m14 16-4-4 4-4\"\u002F>\u003C\u002Fsvg>\u003C\u002Fspan>\n            \u003C\u002Fdiv>\n          \u003C\u002Fsummary>\n          \u003Cpre>\u003Ccode class=\"language-java\" language=java>\u003Cspan class=\"md-editor-code-block\">\u003Cspan class=\"hljs-keyword\">public\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">class\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">SynchronizedHashMap\u003C\u002Fspan>&lt;K, V&gt; {\n    \u003Cspan class=\"hljs-keyword\">private\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">final\u003C\u002Fspan> HashMap&lt;K, V&gt; map = \u003Cspan class=\"hljs-keyword\">new\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">HashMap\u003C\u002Fspan>&lt;&gt;();\n    \u003Cspan class=\"hljs-keyword\">private\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">final\u003C\u002Fspan> \u003Cspan class=\"hljs-type\">Object\u003C\u002Fspan> \u003Cspan class=\"hljs-variable\">lock\u003C\u002Fspan> \u003Cspan class=\"hljs-operator\">=\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">new\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">Object\u003C\u002Fspan>();\n    \n    \u003Cspan class=\"hljs-keyword\">public\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">void\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">put\u003C\u002Fspan>\u003Cspan class=\"hljs-params\">(K key, V value)\u003C\u002Fspan> {\n        \u003Cspan class=\"hljs-keyword\">synchronized\u003C\u002Fspan>(lock) {\n            map.put(key, value);\n        }\n    }\n    \n    \u003Cspan class=\"hljs-keyword\">public\u003C\u002Fspan> V \u003Cspan class=\"hljs-title function_\">get\u003C\u002Fspan>\u003Cspan class=\"hljs-params\">(K key)\u003C\u002Fspan> {\n        \u003Cspan class=\"hljs-keyword\">synchronized\u003C\u002Fspan>(lock) {\n            \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> map.get(key);\n        }\n    }\n}\u003C\u002Fspan>\u003Cspan rn-wrapper aria-hidden=\"true\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\n        \u003C\u002Fdetails>\n      \u003Cp data-line=\"38\">\u003Cstrong>缺点\u003C\u002Fstrong>：性能较差，同一时间只能有一个线程访问。\u003C\u002Fp>\n\u003Ch3 data-line=\"40\" id=\"方案二：读写锁优化\">方案二：读写锁优化\u003C\u002Fh3>\n\n        \u003Cdetails  data-line=\"41\" class=\"md-editor-code\" open=\"\">\n          \u003Csummary class=\"md-editor-code-head\">\n            \u003Cdiv class=\"md-editor-code-flag\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fdiv>\n            \u003Cdiv class=\"md-editor-code-action\">\n              \u003Cspan class=\"md-editor-code-lang\">java\u003C\u002Fspan>\n              \u003Cspan class=\"md-editor-copy-button\" data-tips=\"复制代码\">复制代码\u003C\u002Fspan>\n              \n              \u003Cspan class=\"md-editor-collapse-tips\">\u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"lucide lucide-circle-chevron-left md-editor-icon\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"10\"\u002F>\u003Cpath d=\"m14 16-4-4 4-4\"\u002F>\u003C\u002Fsvg>\u003C\u002Fspan>\n            \u003C\u002Fdiv>\n          \u003C\u002Fsummary>\n          \u003Cpre>\u003Ccode class=\"language-java\" language=java>\u003Cspan class=\"md-editor-code-block\">\u003Cspan class=\"hljs-keyword\">public\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">class\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">ReadWriteLockHashMap\u003C\u002Fspan>&lt;K, V&gt; {\n    \u003Cspan class=\"hljs-keyword\">private\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">final\u003C\u002Fspan> HashMap&lt;K, V&gt; map = \u003Cspan class=\"hljs-keyword\">new\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">HashMap\u003C\u002Fspan>&lt;&gt;();\n    \u003Cspan class=\"hljs-keyword\">private\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">final\u003C\u002Fspan> \u003Cspan class=\"hljs-type\">ReadWriteLock\u003C\u002Fspan> \u003Cspan class=\"hljs-variable\">rwLock\u003C\u002Fspan> \u003Cspan class=\"hljs-operator\">=\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">new\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">ReentrantReadWriteLock\u003C\u002Fspan>();\n    \n    \u003Cspan class=\"hljs-keyword\">public\u003C\u002Fspan> V \u003Cspan class=\"hljs-title function_\">get\u003C\u002Fspan>\u003Cspan class=\"hljs-params\">(K key)\u003C\u002Fspan> {\n        rwLock.readLock().lock();\n        \u003Cspan class=\"hljs-keyword\">try\u003C\u002Fspan> {\n            \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> map.get(key);\n        } \u003Cspan class=\"hljs-keyword\">finally\u003C\u002Fspan> {\n            rwLock.readLock().unlock();\n        }\n    }\n    \n    \u003Cspan class=\"hljs-keyword\">public\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">void\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">put\u003C\u002Fspan>\u003Cspan class=\"hljs-params\">(K key, V value)\u003C\u002Fspan> {\n        rwLock.writeLock().lock();\n        \u003Cspan class=\"hljs-keyword\">try\u003C\u002Fspan> {\n            map.put(key, value);\n        } \u003Cspan class=\"hljs-keyword\">finally\u003C\u002Fspan> {\n            rwLock.writeLock().unlock();\n        }\n    }\n}\u003C\u002Fspan>\u003Cspan rn-wrapper aria-hidden=\"true\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\n        \u003C\u002Fdetails>\n      \u003Cp data-line=\"65\">\u003Cstrong>优势\u003C\u002Fstrong>：允许多个读线程并发访问，提高读密集型应用性能。\u003C\u002Fp>\n\u003Ch2 data-line=\"67\" id=\"2. 分段锁设计（JDK7 ConcurrentHashMap 方案）\">2. 分段锁设计（JDK7 ConcurrentHashMap 方案）\u003C\u002Fh2>\n\u003Cp data-line=\"69\">分段锁将整个哈希表分成多个独立的段（Segment），每个段有自己的锁。\u003C\u002Fp>\n\u003Cp data-line=\"71\">\u003Cstrong>核心设计\u003C\u002Fstrong>：\u003C\u002Fp>\n\u003Cul data-line=\"72\">\n\u003Cli data-line=\"72\">默认 16 个段，可并行访问不同段的数据\u003C\u002Fli>\n\u003Cli data-line=\"73\">段内操作才需要获取锁\u003C\u002Fli>\n\u003Cli data-line=\"74\">显著降低锁竞争概率\u003C\u002Fli>\n\u003C\u002Ful>\n\n        \u003Cdetails  data-line=\"76\" class=\"md-editor-code\" open=\"\">\n          \u003Csummary class=\"md-editor-code-head\">\n            \u003Cdiv class=\"md-editor-code-flag\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fdiv>\n            \u003Cdiv class=\"md-editor-code-action\">\n              \u003Cspan class=\"md-editor-code-lang\">java\u003C\u002Fspan>\n              \u003Cspan class=\"md-editor-copy-button\" data-tips=\"复制代码\">复制代码\u003C\u002Fspan>\n              \n              \u003Cspan class=\"md-editor-collapse-tips\">\u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"lucide lucide-circle-chevron-left md-editor-icon\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"10\"\u002F>\u003Cpath d=\"m14 16-4-4 4-4\"\u002F>\u003C\u002Fsvg>\u003C\u002Fspan>\n            \u003C\u002Fdiv>\n          \u003C\u002Fsummary>\n          \u003Cpre>\u003Ccode class=\"language-java\" language=java>\u003Cspan class=\"md-editor-code-block\">\u003Cspan class=\"hljs-comment\">\u002F\u002F 简化的分段锁实现概念\u003C\u002Fspan>\n\u003Cspan class=\"hljs-keyword\">public\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">class\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">SegmentedHashMap\u003C\u002Fspan>&lt;K, V&gt; {\n    \u003Cspan class=\"hljs-keyword\">private\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">final\u003C\u002Fspan> Segment&lt;K, V&gt;[] segments;\n    \u003Cspan class=\"hljs-keyword\">private\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">static\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">final\u003C\u002Fspan> \u003Cspan class=\"hljs-type\">int\u003C\u002Fspan> \u003Cspan class=\"hljs-variable\">SEGMENT_COUNT\u003C\u002Fspan> \u003Cspan class=\"hljs-operator\">=\u003C\u002Fspan> \u003Cspan class=\"hljs-number\">16\u003C\u002Fspan>;\n    \n    \u003Cspan class=\"hljs-keyword\">static\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">class\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">Segment\u003C\u002Fspan>&lt;K, V&gt; \u003Cspan class=\"hljs-keyword\">extends\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">ReentrantLock\u003C\u002Fspan> {\n        \u003Cspan class=\"hljs-keyword\">private\u003C\u002Fspan> HashMap&lt;K, V&gt; map = \u003Cspan class=\"hljs-keyword\">new\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">HashMap\u003C\u002Fspan>&lt;&gt;();\n    }\n    \n    \u003Cspan class=\"hljs-keyword\">public\u003C\u002Fspan> V \u003Cspan class=\"hljs-title function_\">get\u003C\u002Fspan>\u003Cspan class=\"hljs-params\">(K key)\u003C\u002Fspan> {\n        \u003Cspan class=\"hljs-type\">int\u003C\u002Fspan> \u003Cspan class=\"hljs-variable\">segmentIndex\u003C\u002Fspan> \u003Cspan class=\"hljs-operator\">=\u003C\u002Fspan> hash(key) &amp; (SEGMENT_COUNT - \u003Cspan class=\"hljs-number\">1\u003C\u002Fspan>);\n        Segment&lt;K, V&gt; segment = segments[segmentIndex];\n        segment.lock();\n        \u003Cspan class=\"hljs-keyword\">try\u003C\u002Fspan> {\n            \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> segment.map.get(key);\n        } \u003Cspan class=\"hljs-keyword\">finally\u003C\u002Fspan> {\n            segment.unlock();\n        }\n    }\n}\u003C\u002Fspan>\u003Cspan rn-wrapper aria-hidden=\"true\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\n        \u003C\u002Fdetails>\n      \u003Ch2 data-line=\"99\" id=\"3. JDK8+ ConcurrentHashMap 的进化\">3. JDK8+ ConcurrentHashMap 的进化\u003C\u002Fh2>\n\u003Cp data-line=\"101\">JDK8 的 ConcurrentHashMap 放弃了分段锁，采用更精细的锁机制：\u003C\u002Fp>\n\u003Ch3 data-line=\"103\" id=\"核心技术：\">核心技术：\u003C\u002Fh3>\n\u003Cul data-line=\"104\">\n\u003Cli data-line=\"104\">\u003Cstrong>Node + synchronized + CAS\u003C\u002Fstrong>\u003C\u002Fli>\n\u003Cli data-line=\"105\">\u003Cstrong>链表转红黑树\u003C\u002Fstrong>（当链表长度 ≥ 8）\u003C\u002Fli>\n\u003Cli data-line=\"106\">\u003Cstrong>多线程协同扩容\u003C\u002Fstrong>\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch3 data-line=\"108\" id=\"锁粒度优化：\">锁粒度优化：\u003C\u002Fh3>\n\u003Cp data-line=\"109\">从分段锁（锁定多个桶）细化到\u003Cstrong>桶级别锁\u003C\u002Fstrong>（只锁定单个链表\u002F树的头节点）。\u003C\u002Fp>\n\u003Ch1 data-line=\"111\" id=\"⚡ 无锁线程安全 HashMap 设计方案\">⚡ 无锁线程安全 HashMap 设计方案\u003C\u002Fh1>\n\u003Ch2 data-line=\"113\" id=\"1. CAS（Compare-And-Swap）基础\">1. CAS（Compare-And-Swap）基础\u003C\u002Fh2>\n\u003Cp data-line=\"115\">CAS 是无锁算法的核心，通过硬件保证操作的原子性：\u003C\u002Fp>\n\n        \u003Cdetails  data-line=\"117\" class=\"md-editor-code\" open=\"\">\n          \u003Csummary class=\"md-editor-code-head\">\n            \u003Cdiv class=\"md-editor-code-flag\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fdiv>\n            \u003Cdiv class=\"md-editor-code-action\">\n              \u003Cspan class=\"md-editor-code-lang\">java\u003C\u002Fspan>\n              \u003Cspan class=\"md-editor-copy-button\" data-tips=\"复制代码\">复制代码\u003C\u002Fspan>\n              \n              \u003Cspan class=\"md-editor-collapse-tips\">\u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"lucide lucide-circle-chevron-left md-editor-icon\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"10\"\u002F>\u003Cpath d=\"m14 16-4-4 4-4\"\u002F>\u003C\u002Fsvg>\u003C\u002Fspan>\n            \u003C\u002Fdiv>\n          \u003C\u002Fsummary>\n          \u003Cpre>\u003Ccode class=\"language-java\" language=java>\u003Cspan class=\"md-editor-code-block\">\u003Cspan class=\"hljs-keyword\">public\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">class\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">AtomicExample\u003C\u002Fspan> {\n    \u003Cspan class=\"hljs-keyword\">private\u003C\u002Fspan> \u003Cspan class=\"hljs-type\">AtomicInteger\u003C\u002Fspan> \u003Cspan class=\"hljs-variable\">value\u003C\u002Fspan> \u003Cspan class=\"hljs-operator\">=\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">new\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">AtomicInteger\u003C\u002Fspan>(\u003Cspan class=\"hljs-number\">0\u003C\u002Fspan>);\n    \n    \u003Cspan class=\"hljs-keyword\">public\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">void\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">increment\u003C\u002Fspan>\u003Cspan class=\"hljs-params\">()\u003C\u002Fspan> {\n        \u003Cspan class=\"hljs-type\">int\u003C\u002Fspan> oldValue, newValue;\n        \u003Cspan class=\"hljs-keyword\">do\u003C\u002Fspan> {\n            oldValue = value.get();\n            newValue = oldValue + \u003Cspan class=\"hljs-number\">1\u003C\u002Fspan>;\n        } \u003Cspan class=\"hljs-keyword\">while\u003C\u002Fspan> (!value.compareAndSet(oldValue, newValue));\n    }\n}\u003C\u002Fspan>\u003Cspan rn-wrapper aria-hidden=\"true\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\n        \u003C\u002Fdetails>\n      \u003Ch2 data-line=\"131\" id=\"2. 无锁 HashMap 关键技术\">2. 无锁 HashMap 关键技术\u003C\u002Fh2>\n\u003Ch3 data-line=\"133\" id=\"原子引用数组\">原子引用数组\u003C\u002Fh3>\n\n        \u003Cdetails  data-line=\"134\" class=\"md-editor-code\" open=\"\">\n          \u003Csummary class=\"md-editor-code-head\">\n            \u003Cdiv class=\"md-editor-code-flag\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fdiv>\n            \u003Cdiv class=\"md-editor-code-action\">\n              \u003Cspan class=\"md-editor-code-lang\">java\u003C\u002Fspan>\n              \u003Cspan class=\"md-editor-copy-button\" data-tips=\"复制代码\">复制代码\u003C\u002Fspan>\n              \n              \u003Cspan class=\"md-editor-collapse-tips\">\u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"lucide lucide-circle-chevron-left md-editor-icon\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"10\"\u002F>\u003Cpath d=\"m14 16-4-4 4-4\"\u002F>\u003C\u002Fsvg>\u003C\u002Fspan>\n            \u003C\u002Fdiv>\n          \u003C\u002Fsummary>\n          \u003Cpre>\u003Ccode class=\"language-java\" language=java>\u003Cspan class=\"md-editor-code-block\">\u003Cspan class=\"hljs-keyword\">public\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">class\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">LockFreeHashMap\u003C\u002Fspan>&lt;K, V&gt; {\n    \u003Cspan class=\"hljs-keyword\">private\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">final\u003C\u002Fspan> AtomicReference&lt;Node&lt;K, V&gt;[]&gt; table;\n    \n    \u003Cspan class=\"hljs-keyword\">public\u003C\u002Fspan> V \u003Cspan class=\"hljs-title function_\">get\u003C\u002Fspan>\u003Cspan class=\"hljs-params\">(K key)\u003C\u002Fspan> {\n        \u003Cspan class=\"hljs-comment\">\u002F\u002F 无锁读取：依赖 volatile 内存语义\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-type\">int\u003C\u002Fspan> \u003Cspan class=\"hljs-variable\">index\u003C\u002Fspan> \u003Cspan class=\"hljs-operator\">=\u003C\u002Fspan> hash(key) &amp; (table.length() - \u003Cspan class=\"hljs-number\">1\u003C\u002Fspan>);\n        Node&lt;K, V&gt; node = table.get(index);\n        \u003Cspan class=\"hljs-keyword\">while\u003C\u002Fspan> (node != \u003Cspan class=\"hljs-literal\">null\u003C\u002Fspan>) {\n            \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (node.key.equals(key)) \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> node.value;\n            node = node.next;\n        }\n        \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-literal\">null\u003C\u002Fspan>;\n    }\n}\u003C\u002Fspan>\u003Cspan rn-wrapper aria-hidden=\"true\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\n        \u003C\u002Fdetails>\n      \u003Ch3 data-line=\"151\" id=\"无锁插入实现要点：\">无锁插入实现要点：\u003C\u002Fh3>\n\u003Col data-line=\"152\">\n\u003Cli data-line=\"152\">\u003Cstrong>原子查找定位\u003C\u002Fstrong>：使用 CAS 保证查找-插入的原子性\u003C\u002Fli>\n\u003Cli data-line=\"153\">\u003Cstrong>无锁链表管理\u003C\u002Fstrong>：通过原子引用实现链表操作\u003C\u002Fli>\n\u003Cli data-line=\"154\">\u003Cstrong>智能排序策略\u003C\u002Fstrong>：节点按特定规则排序，简化 rehash\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Ch2 data-line=\"156\" id=\"3. 应对 rehash 挑战\">3. 应对 rehash 挑战\u003C\u002Fh2>\n\u003Cp data-line=\"158\">rehash 是无锁 HashMap 的最大技术难点，解决方案：\u003C\u002Fp>\n\u003Ch3 data-line=\"160\" id=\"惰性 rehash 策略\">惰性 rehash 策略\u003C\u002Fh3>\n\u003Cul data-line=\"161\">\n\u003Cli data-line=\"161\">不立即移动所有节点\u003C\u002Fli>\n\u003Cli data-line=\"162\">在访问时逐步迁移\u003C\u002Fli>\n\u003Cli data-line=\"163\">使用转发节点标记正在迁移的桶\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch3 data-line=\"165\" id=\"一致性哈希技巧\">一致性哈希技巧\u003C\u002Fh3>\n\u003Cp data-line=\"166\">通过特殊的哈希位反转排序，使节点在 rehash 时保持相对顺序，避免数据移动。\u003C\u002Fp>\n\u003Ch1 data-line=\"168\" id=\"📊 方案对比与选择指南\">📊 方案对比与选择指南\u003C\u002Fh1>\n\u003Cp data-line=\"170\">下表总结了不同方案的特性对比：\u003C\u002Fp>\n\u003Ctable data-line=\"172\">\n\u003Cthead data-line=\"172\">\n\u003Ctr data-line=\"172\">\n\u003Cth>方案\u003C\u002Fth>\n\u003Cth>线程安全\u003C\u002Fth>\n\u003Cth>性能\u003C\u002Fth>\n\u003Cth>实现复杂度\u003C\u002Fth>\n\u003Cth>适用场景\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody data-line=\"174\">\n\u003Ctr data-line=\"174\">\n\u003Ctd>全局锁\u003C\u002Ftd>\n\u003Ctd>✅\u003C\u002Ftd>\n\u003Ctd>低\u003C\u002Ftd>\n\u003Ctd>简单\u003C\u002Ftd>\n\u003Ctd>低并发，简单应用\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr data-line=\"175\">\n\u003Ctd>读写锁\u003C\u002Ftd>\n\u003Ctd>✅\u003C\u002Ftd>\n\u003Ctd>中\u003C\u002Ftd>\n\u003Ctd>中等\u003C\u002Ftd>\n\u003Ctd>读多写少\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr data-line=\"176\">\n\u003Ctd>分段锁\u003C\u002Ftd>\n\u003Ctd>✅\u003C\u002Ftd>\n\u003Ctd>中高\u003C\u002Ftd>\n\u003Ctd>复杂\u003C\u002Ftd>\n\u003Ctd>中等并发\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr data-line=\"177\">\n\u003Ctd>ConcurrentHashMap\u003C\u002Ftd>\n\u003Ctd>✅\u003C\u002Ftd>\n\u003Ctd>高\u003C\u002Ftd>\n\u003Ctd>极复杂\u003C\u002Ftd>\n\u003Ctd>高并发生产环境\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr data-line=\"178\">\n\u003Ctd>无锁实现\u003C\u002Ftd>\n\u003Ctd>✅\u003C\u002Ftd>\n\u003Ctd>极高\u003C\u002Ftd>\n\u003Ctd>极其复杂\u003C\u002Ftd>\n\u003Ctd>极限性能需求\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\n\u003Ch1 data-line=\"180\" id=\"💡 实践建议\">💡 实践建议\u003C\u002Fh1>\n\u003Col data-line=\"182\">\n\u003Cli data-line=\"182\">\n\u003Cp data-line=\"182\">\u003Cstrong>优先使用 ConcurrentHashMap\u003C\u002Fstrong>\u003Cbr>\n对于大多数应用场景，JDK 提供的 ConcurrentHashMap 是最佳选择。\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli data-line=\"185\">\n\u003Cp data-line=\"185\">\u003Cstrong>谨慎考虑自定义无锁实现\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cul data-line=\"186\">\n\u003Cli data-line=\"186\">无锁编程极其复杂，容易出错\u003C\u002Fli>\n\u003Cli data-line=\"187\">需要深入的并发知识和严格的测试\u003C\u002Fli>\n\u003Cli data-line=\"188\">仅在性能瓶颈明确且 ConcurrentHashMap 无法满足时考虑\u003C\u002Fli>\n\u003C\u002Ful>\n\u003C\u002Fli>\n\u003Cli data-line=\"190\">\n\u003Cp data-line=\"190\">\u003Cstrong>原子操作的合理使用\u003C\u002Fstrong>\u003C\u002Fp>\n\n        \u003Cdetails  data-line=\"191\" class=\"md-editor-code\" open=\"\">\n          \u003Csummary class=\"md-editor-code-head\">\n            \u003Cdiv class=\"md-editor-code-flag\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fdiv>\n            \u003Cdiv class=\"md-editor-code-action\">\n              \u003Cspan class=\"md-editor-code-lang\">java\u003C\u002Fspan>\n              \u003Cspan class=\"md-editor-copy-button\" data-tips=\"复制代码\">复制代码\u003C\u002Fspan>\n              \n              \u003Cspan class=\"md-editor-collapse-tips\">\u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"lucide lucide-circle-chevron-left md-editor-icon\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"10\"\u002F>\u003Cpath d=\"m14 16-4-4 4-4\"\u002F>\u003C\u002Fsvg>\u003C\u002Fspan>\n            \u003C\u002Fdiv>\n          \u003C\u002Fsummary>\n          \u003Cpre>\u003Ccode class=\"language-java\" language=java>\u003Cspan class=\"md-editor-code-block\">\u003Cspan class=\"hljs-comment\">\u002F\u002F 使用内置原子方法，避免手动同步\u003C\u002Fspan>\nconcurrentMap.compute(\u003Cspan class=\"hljs-string\">&quot;key&quot;\u003C\u002Fspan>, (k, v) -&gt; v == \u003Cspan class=\"hljs-literal\">null\u003C\u002Fspan> ? \u003Cspan class=\"hljs-number\">1\u003C\u002Fspan> : v + \u003Cspan class=\"hljs-number\">1\u003C\u002Fspan>);\u003C\u002Fspan>\u003Cspan rn-wrapper aria-hidden=\"true\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\n        \u003C\u002Fdetails>\n      \u003C\u002Fli>\n\u003C\u002Fol>\n\u003Ch1 data-line=\"196\" id=\"💎 总结\">💎 总结\u003C\u002Fh1>\n\u003Cp data-line=\"198\">HashMap 确实是非线程安全的，在多线程环境下必须使用同步机制。从简单的全局锁到精细的分段锁，再到复杂的无锁实现，各种方案在性能与复杂度之间有不同的权衡。对于绝大多数实际项目，推荐使用 JDK 提供的 ConcurrentHashMap，它经过了充分测试和优化，能够满足高并发场景的需求。\u003C\u002Fp>\n\u003Cp data-line=\"200\">希望这份详细的解答能帮助你更好地理解 HashMap 的线程安全问题和解决方案！如果你有特定场景的需求，我可以提供更具体的设计建议。\u003C\u002Fp>\n",4270,14,"0","",2,0,442,"锁,线,HashMap,实现,K","HashMap 的线程安全性是多线程编程中的一个重要问题，下面我将为你详细解答，并探讨线程安全 HashMap 的设计方案。\n🔒 HashMap 的线程安全性分析\nHashMap 的非线程安全本质\nHashMap 在设计上不是线程安全的。当多个线程同时访问和修改同一个 HashMap 实例时，会导致不可预知的行为。","2026-01-13 11:18:25"]