{"id":26713,"date":"2023-04-27T13:36:56","date_gmt":"2023-04-27T05:36:56","guid":{"rendered":"https:\/\/docs.pingcode.com\/?p=26713"},"modified":"2023-07-31T01:31:07","modified_gmt":"2023-07-30T17:31:07","slug":"concurrenthashmap%e5%bc%b1%e4%b8%80%e8%87%b4%e7%9a%84%e8%bf%ad%e4%bb%a3%e5%99%a8%e6%98%af%e4%bb%80%e4%b9%88%e5%8e%9f%e7%90%86","status":"publish","type":"post","link":"https:\/\/docs.pingcode.com\/ask\/26713.html","title":{"rendered":"ConcurrentHashMap\u5f31\u4e00\u81f4\u7684\u8fed\u4ee3\u5668\u662f\u4ec0\u4e48\u539f\u7406"},"content":{"rendered":"<blockquote class=\"wp-block-quote\">\n<p>ConcurrentHashMap\u5f31\u4e00\u81f4\u7684\u8fed\u4ee3\u5668\u7684\u539f\u7406\u662f\uff1aConcurrentHashMap \u7684\u5f31\u4e00\u81f4\u6027\u8fed\u4ee3\u5668\u662f\u57fa\u4e8e\u5feb\u7167\u8fed\u4ee3\u5668\u5b9e\u73b0\u7684\u3002\u5728 ConcurrentHashMap \u4e2d\uff0c\u6bcf\u4e2a Segment \u7ef4\u62a4\u4e86\u4e00\u4e2a\u5143\u7d20\u8ba1\u6570\u5668 modCount \u548c\u4e00\u4e2a\u4fee\u6539\u6b21\u6570\u8ba1\u6570\u5668 count\u3002<\/p>\n<\/blockquote>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img fetchpriority=\"high\" alt=\"\" class=\"wp-image-26717\" decoding=\"async\" height=\"576\" sizes=\"(max-width: 1024px) 100vw, 1024px\" src=\"https:\/\/cdn-docs.pingcode.com\/wp-content\/uploads\/2023\/04\/\u6570\u636e\u7ed3\u6784\u9002\u7528\u4e8e\u89e3\u51b3\u4ec0\u4e48\u95ee\u9898-1-1024x576.png?x-oss-process=image\/auto-orient,1\/format,webp\" srcset=\"https:\/\/cdn-docs.pingcode.com\/wp-content\/uploads\/2023\/04\/\u6570\u636e\u7ed3\u6784\u9002\u7528\u4e8e\u89e3\u51b3\u4ec0\u4e48\u95ee\u9898-1-1024x576.png?x-oss-process=image\/auto-orient,1\/format,webp 1024w, https:\/\/cdn-docs.pingcode.com\/wp-content\/uploads\/2023\/04\/\u6570\u636e\u7ed3\u6784\u9002\u7528\u4e8e\u89e3\u51b3\u4ec0\u4e48\u95ee\u9898-1-300x169.png 300w, https:\/\/cdn-docs.pingcode.com\/wp-content\/uploads\/2023\/04\/\u6570\u636e\u7ed3\u6784\u9002\u7528\u4e8e\u89e3\u51b3\u4ec0\u4e48\u95ee\u9898-1-768x432.png 768w, https:\/\/cdn-docs.pingcode.com\/wp-content\/uploads\/2023\/04\/\u6570\u636e\u7ed3\u6784\u9002\u7528\u4e8e\u89e3\u51b3\u4ec0\u4e48\u95ee\u9898-1-270x152.png 270w, https:\/\/cdn-docs.pingcode.com\/wp-content\/uploads\/2023\/04\/\u6570\u636e\u7ed3\u6784\u9002\u7528\u4e8e\u89e3\u51b3\u4ec0\u4e48\u95ee\u9898-1-1536x865.png 1536w, https:\/\/cdn-docs.pingcode.com\/wp-content\/uploads\/2023\/04\/\u6570\u636e\u7ed3\u6784\u9002\u7528\u4e8e\u89e3\u51b3\u4ec0\u4e48\u95ee\u9898-1.png 1993w\" width=\"1024\"\/><\/figure>\n<\/div>\n<h2 class=\"wp-block-heading\">\u4e00\u3001ConcurrentHashMap\u5f31\u4e00\u81f4\u7684\u8fed\u4ee3\u5668\u662f\u4ec0\u4e48\u539f\u7406<\/h2>\n<p>ConcurrentHashMap \u7684\u5f31\u4e00\u81f4\u6027\u8fed\u4ee3\u5668\u662f\u57fa\u4e8e\u5feb\u7167\u8fed\u4ee3\u5668\u5b9e\u73b0\u7684\u3002\u5728 ConcurrentHashMap \u4e2d\uff0c\u6bcf\u4e2a Segment\uff08\u5373 ConcurrentHashMap \u4e2d\u6bcf\u4e2a key-value \u5bf9\u6240\u5728\u7684 segment\uff09\u7ef4\u62a4\u4e86\u4e00\u4e2a\u5143\u7d20\u8ba1\u6570\u5668 modCount \u548c\u4e00\u4e2a\u4fee\u6539\u6b21\u6570\u8ba1\u6570\u5668 count\u3002\u5f53 segment \u53d1\u751f\u4fee\u6539\u64cd\u4f5c\u65f6\uff0ccount \u8ba1\u6570\u5668\u4f1a\u81ea\u589e\uff0c\u540c\u65f6 modCount \u8ba1\u6570\u5668\u4e5f\u4f1a\u81ea\u589e\u3002\u5f53\u4f7f\u7528\u8fed\u4ee3\u5668\u5bf9 ConcurrentHashMap \u8fdb\u884c\u904d\u5386\u65f6\uff0c\u8fed\u4ee3\u5668\u4f1a\u5728\u6bcf\u6b21\u8bbf\u95ee\u4e4b\u524d\uff0c\u8bb0\u5f55\u5f53\u524d modCount \u503c\uff0c\u82e5\u5728\u8fed\u4ee3\u8fc7\u7a0b\u4e2d ConcurrentHashMap \u53d1\u751f\u4e86\u4fee\u6539\u64cd\u4f5c\uff0cmodCount \u503c\u4f1a\u53d1\u751f\u53d8\u5316\uff0c\u8fed\u4ee3\u5668\u4f1a\u53d1\u73b0\u8fd9\u4e2a\u53d8\u5316\uff0c\u4f1a\u629b\u51fa ConcurrentModificationException \u5f02\u5e38\u3002<\/p>\n<p>\u56e0\u6b64\uff0cConcurrentHashMap \u8fed\u4ee3\u5668\u7684\u5f31\u4e00\u81f4\u6027\u4f53\u73b0\u5728\u5b83\u4e0d\u4fdd\u8bc1\u904d\u5386\u7ed3\u679c\u5373\u4f7f\u5728\u8fed\u4ee3\u8fc7\u7a0b\u4e2d ConcurrentHashMap \u53d1\u751f\u4e86\u4fee\u6539\uff0c\u4f46\u5b83\u4fdd\u8bc1\u8fed\u4ee3\u5668\u4e0d\u4f1a\u56e0\u4e3a\u5728\u904d\u5386\u65f6 ConcurrentHashMap \u5305\u542b\u4e86\u65b0\u5143\u7d20\u800c\u629b\u51fa\u5f02\u5e38\u3002\u540c\u65f6\u8fd9\u79cd\u8bbe\u8ba1\u4e5f\u80fd\u4fdd\u8bc1\u5728\u5927\u591a\u6570\u60c5\u51b5\u4e0b\uff0c\u8fed\u4ee3\u5668\u8bbf\u95ee\u7684\u5143\u7d20\u90fd\u4e0d\u4f1a\u592a\u8fc7\u9648\u65e7\uff0c\u53ef\u4ee5\u6ee1\u8db3\u8fed\u4ee3\u5668\u7684\u7edd\u5927\u90e8\u5206\u4f7f\u7528\u573a\u666f\u3002<\/p>\n<h2 class=\"wp-block-heading\">\u4e8c\u3001ConcurrentHashMap\u7b80\u4ecb<\/h2>\n<p>java.util.concurrent.ConcurrentHashMap \u5c5e\u4e8e JUC \u5305\u4e0b\u7684\u4e00\u4e2a\u96c6\u5408\u7c7b\uff0c\u53ef\u4ee5\u5b9e\u73b0\u7ebf\u7a0b\u5b89\u5168\u3002\u5b83\u7531\u591a\u4e2a Segment \u7ec4\u5408\u800c\u6210\u3002Segment \u672c\u8eab\u5c31\u76f8\u5f53\u4e8e\u4e00\u4e2a HashMap \u5bf9\u8c61\u3002\u540c HashMap \u4e00\u6837\uff0cSegment \u5305\u542b\u4e00\u4e2a HashEntry \u6570\u7ec4\uff0c\u6570\u7ec4\u4e2d\u7684\u6bcf\u4e00\u4e2a HashEntry \u65e2\u662f\u4e00\u4e2a\u952e\u503c\u5bf9\uff0c\u4e5f\u662f\u4e00\u4e2a\u94fe\u8868\u7684\u5934\u8282\u70b9\u3002<\/p>\n<p>ConcurrentHashMap\u7684put\u65b9\u6cd5\u6d41\u7a0b\uff08JDK1.7\uff09\uff1a<\/p>\n<pre class=\"wp-block-code\"><code>   public V put(K key, V value) {\n       \/\/key\uff0cvalue\u4e0d\u80fd\u4e3anull\n        Segment&lt;K,V&gt; s;\n        if (value == null)\n            throw new NullPointerException();\n       \/\/\u901a\u8fc7key\u8fdb\u884c\u54c8\u5e0c\u5230\u5bf9\u5e94segment\u4f4d\u7f6e\n        int hash = hash(key);\n        int j = (hash &gt;&gt;&gt; segmentShift) &amp; segmentMask;\n        \/\/\u901a\u8fc7\u4f4d\u7f6ej\u83b7\u53d6\u5f53\u524d\u7684\u5bf9\u5e94segment\u8d77\u59cb\u4f4d\u7f6e\n        if ((s = (Segment&lt;K,V&gt;)UN<a href=\"https:\/\/docs.pingcode.com\/agile\/agile-at-scale\/what-is-safe\" target=\"_blank\">SAFe<\/a>.getObject          \/\/ nonvolatile; recheck\n             (segments, (j &lt;&lt; SSHIFT) + SBASE)) == null) \/\/  in ensureSegment\n            s = ensureSegment(j);\n        return s.put(key, hash, value, false);\n    }\n\n  #\u5185\u90e8\u7c7bSegment\u4e0b\u7684put\u65b9\u6cd5\n        final V put(K key, int hash, V value, boolean onlyIfAbsent) {\n            \/\/\u5c1d\u8bd5\u6027\u52a0\u9501\n            HashEntry&lt;K,V&gt; node = tryLock() ? null :\n                scanAndLockForPut(key, hash, value);\n            V oldValue;\n            try {\n                \/\/\u5f53\u524dsegment\u4e0b\u7684table\n                HashEntry&lt;K,V&gt;[] tab = table;\n                \/\/\u901a\u8fc7key\u7684\u54c8\u5e0c\u503c\u8fdb\u884c\u54c8\u5e0c\u627e\u5230\u5bf9\u5e94table\u4f4d\u7f6e\n                int index = (tab.length - 1) &amp; hash;\n                HashEntry&lt;K,V&gt; first = entryAt(tab, index);\n                for (HashEntry&lt;K,V&gt; e = first;;) {\n                    if (e != null) {\n                        K k;\n                        if ((k = e.key) == key ||(e.hash == hash &amp;&amp; key.equals(k))) {\n                            oldValue = e.value;\n                            if (!onlyIfAbsent) {\n                            \/\/put\u65b9\u6cd5\u5904\u7406\uff1a\u5c06\u65b0value\u66ff\u6362oldvalue\n                                e.value = value;\n                                ++modCount;\n                            }\n                            break;\n                        }\n                        e = e.next;\n                    } else {\n                        if (node != null)\n                            node.setNext(first);\n                        else\n                            node = new HashEntry&lt;K,V&gt;(hash, key, value, first);\n                        int c = count + 1;\n                        if (c &gt; threshold &amp;&amp; tab.length &lt; MAXIMUM_CAPACITY)\n                        \/\/\u8d85\u8fc7\u6269\u5bb9\u9608\u503c\n                            rehash(node);\n                        else\n                            setEntryAt(tab, index, node);\n                        ++modCount;\n                        count = c;\n                        oldValue = null;\n                        break;\n                    }\n                }\n            } finally {\n            \/\/\u91ca\u653e\u9501\n                unlock();\n            }\n            return oldValue;\n        }\n        \n     \/\/\u6269\u5bb9\u4ec5\u9488\u5bf9\u67d0\u4e2asegment\u8fdb\u884c\u6269\u5bb9\uff0c\u800c\u4e0d\u662f\u5bf9\u6574\u4e2aConcurrentHashMap\u8fdb\u884c\u6269\u5bb9\n      private void rehash(HashEntry&lt;K,V&gt; node) {\n          \/\/\u5728segment\u4e0b\u7684table\n            HashEntry&lt;K,V&gt;[] oldTable = table;\n            int oldCapacity = oldTable.length;\n            \/\/\u6309\u7167\u539f\u5927\u5c0f2\u500d\u5173\u7cfb\u8fdb\u884c\u6269\u5bb9 \n            int newCapacity = oldCapacity &lt;&lt; 1;\n            threshold = (int)(newCapacity * loadFactor);\n            HashEntry&lt;K,V&gt;[] newTable =(HashEntry&lt;K,V&gt;[]) new HashEntry[newCapacity];\n            int sizeMask = newCapacity - 1;\n            \/\/\u5c06\u539f\u6709table\u4e0a\u7684\u6240\u6709hashentry\u8282\u70b9\u8fdb\u884c\u91cd\u65b0\u54c8\u5e0c\u5230\u65b0table\u4e0a\n            for (int i = 0; i &lt; oldCapacity ; i++) {\n                HashEntry&lt;K,V&gt; e = oldTable[i];\n                if (e != null) {\n                    HashEntry&lt;K,V&gt; next = e.next;\n                    int idx = e.hash &amp; sizeMask;\n                    if (next == null)   \/\/  Single node on list\n                        newTable[idx] = e;\n                    else { \/\/ Reuse consecutive sequence at same slot\n                        HashEntry&lt;K,V&gt; lastRun = e;\n                        int lastIdx = idx;\n                        for (HashEntry&lt;K,V&gt; last = next;\n                             last != null;\n                             last = last.next) {\n                            int k = last.hash &amp; sizeMask;\n                            if (k != lastIdx) {\n                                lastIdx = k;\n                                lastRun = last;\n                            }\n                        }\n                        newTable[lastIdx] = lastRun;\n                        \/\/ Clone remaining nodes\n                        for (HashEntry&lt;K,V&gt; p = e; p != lastRun; p = p.next) {\n                            V v = p.value;\n                            int h = p.hash;\n                            int k = h &amp; sizeMask;\n                            HashEntry&lt;K,V&gt; n = newTable[k];\n                            newTable[k] = new HashEntry&lt;K,V&gt;(h, p.key, v, n);\n                        }\n                    }\n                }\n            }\n            int nodeIndex = node.hash &amp; sizeMask; \/\/ add the new node\n            node.setNext(newTable[nodeIndex]);\n            newTable[nodeIndex] = node;\n            table = newTable;\n        }<\/code><\/pre>\n<h2 class=\"wp-block-heading\">\u4e09\u3001ConcurrentHashMap\u548cHashMap\u7684\u533a\u522b<\/h2>\n<p>ConcurrentHashMap\u548cHashMap\u7684\u533a\u522b\u5982\u4e0b\uff1a<\/p>\n<ol>\n<li>HashMap\u662f\u975e\u7ebf\u7a0b\u5b89\u5168\u7684\uff1b\u800cConcurrentHashMap\u662f\u7ebf\u7a0b\u5b89\u5168\u7684\u3002<\/li>\n<li>HashMap\u7684key\u548cvalue\u5747\u53ef\u4ee5\u4e3anull\uff1b\u800cConcurrentHashMap\u7684key\u548cvalue\u5747\u4e0d\u53ef\u4ee5\u4e3anull\u3002<\/li>\n<li>HashMap\u662f\u901a\u8fc7\u7ed9\u6574\u5f20\u6563\u5217\u8868\u52a0\u9501\u7684\u65b9\u5f0f\u6765\u4fdd\u8bc1\u7ebf\u7a0b\u5b89\u5168\uff0c\u8fd9\u79cd\u65b9\u5f0f\u4fdd\u8bc1\u4e86\u7ebf\u7a0b\u5b89\u5168\uff0c\u4f46\u662f\u5e76\u53d1\u6267\u884c\u6548\u7387\u4f4e\u4e0b\uff1bConcurrentHashMap\u5728JDK1.8\u4e4b\u524d\uff0c\u91c7\u7528\u5206\u6bb5\u9501\u673a\u5236\u6765\u4fdd\u8bc1\u7ebf\u7a0b\u5b89\u5168\u7684\uff0c\u8fd9\u79cd\u65b9\u5f0f\u53ef\u4ee5\u5728\u4fdd\u8bc1\u7ebf\u7a0b\u5b89\u5168\u7684\u540c\u65f6\uff0c\u4e00\u5b9a\u7a0b\u5ea6\u4e0a\u63d0\u9ad8\u5e76\u53d1\u6267\u884c\u6548\u7387\uff08\u5f53\u591a\u7ebf\u7a0b\u5e76\u53d1\u8bbf\u95ee\u4e0d\u540c\u7684segment\u65f6\uff0c\u591a\u7ebf\u7a0b\u5c31\u662f\u5b8c\u5168\u5e76\u53d1\u7684\uff0c\u5e76\u53d1\u6267\u884c\u6548\u7387\u4f1a\u63d0\u9ad8\uff09\u3002\u4f46\u4eceJDK1.8\u5f00\u59cb\uff0cConcurrentHashMap\u6570\u636e\u7ed3\u6784\u4e0e1.8\u4e2d\u7684HashMap\u4fdd\u6301\u4e00\u81f4\uff0c\u5747\u4e3a\u6570\u7ec4+\u94fe\u8868+\u7ea2\u9ed1\u6811\uff0c\u662f\u901a\u8fc7\u4e50\u89c2\u9501+Synchronized\u6765\u4fdd\u8bc1\u7ebf\u7a0b\u5b89\u5168\u7684\u3002\u5f53\u591a\u7ebf\u7a0b\u5e76\u53d1\u5411\u540c\u4e00\u4e2a\u6563\u5217\u6876\u6dfb\u52a0\u5143\u7d20\u65f6\u3002\u82e5\u6563\u5217\u6876\u4e3a\u7a7a\uff0c\u6b64\u65f6\u89e6\u53d1\u4e50\u89c2\u9501\u673a\u5236\uff0c\u7ebf\u7a0b\u4f1a\u83b7\u53d6\u5230\u6876\u4e2d\u7684\u7248\u672c\u53f7\uff0c\u5728\u6dfb\u52a0\u8282\u70b9\u4e4b\u524d\uff0c\u5224\u65ad\u7ebf\u7a0b\u4e2d\u83b7\u53d6\u7684\u7248\u672c\u53f7\u4e0e\u6876\u4e2d\u5b9e\u9645\u5b58\u5728\u7684\u7248\u672c\u53f7\u662f\u5426\u4e00\u81f4\uff0c\u82e5\u4e00\u81f4\uff0c\u5219\u6dfb\u52a0\u6210\u529f\uff0c\u82e5\u4e0d\u4e00\u81f4\uff0c\u5219\u8ba9\u7ebf\u7a0b\u81ea\u65cb\u3002<\/li>\n<\/ol>\n<p><strong><em>\u5ef6\u4f38\u9605\u8bfb1\uff1aJDK1.7 \u4e0e JDK1.8 \u4e2d ConcurrentHashMap \u7684\u533a\u522b<\/em><\/strong><\/p>\n<ul>\n<li><strong>\u6570\u636e\u7ed3\u6784<\/strong>\uff1a\u53d6\u6d88\u4e86 Segment \u5206\u6bb5\u9501\u7684\u6570\u636e\u7ed3\u6784\uff0c\u53d6\u800c\u4ee3\u4e4b\u7684\u662f\u6570\u7ec4+\u94fe\u8868+\u7ea2\u9ed1\u6811\u7684\u7ed3\u6784\u3002<\/li>\n<li><strong>\u4fdd\u8bc1\u7ebf\u7a0b\u5b89\u5168\u673a\u5236<\/strong>\uff1aJDK1.7 \u91c7\u7528Segment \u7684\u5206\u6bb5\u9501\u673a\u5236\u5b9e\u73b0\u7ebf\u7a0b\u5b89\u5168\uff0c\u5176\u4e2d Segment \u7ee7\u627f\u81ea ReentrantLock \u3002JDK1.8\u91c7\u7528CAS+synchronized\u4fdd\u8bc1\u7ebf\u7a0b\u5b89\u5168\u3002<\/li>\n<li><strong>\u9501\u7684\u7c92\u5ea6<\/strong>\uff1aJDK1.7 \u662f\u5bf9\u9700\u8981\u8fdb\u884c\u6570\u636e\u64cd\u4f5c\u7684 Segment \u52a0\u9501\uff0cJDK1.8\u8c03\u6574\u4e3a\u5bf9\u6bcf\u4e2a\u6570\u7ec4\u5143\u7d20\u52a0\u9501\uff08Node\uff09\u3002<\/li>\n<li><strong>\u94fe\u8868\u8f6c\u5316\u4e3a\u7ea2\u9ed1\u6811<\/strong>\uff1a\u5b9a\u4f4d\u8282\u70b9\u7684 hash \u7b97\u6cd5\u7b80\u5316\u4f1a\u5e26\u6765\u5f0a\u7aef\uff0chash\u51b2\u7a81\u52a0\u5267\uff0c\u56e0\u6b64\u5728\u94fe\u8868\u8282\u70b9\u6570\u91cf\u5927\u4e8e 8\uff08\u4e14\u6570\u636e\u603b\u91cf\u5927\u4e8e\u7b49\u4e8e 64\uff09\u65f6\uff0c\u4f1a\u5c06\u94fe\u8868\u8f6c\u5316\u4e3a\u7ea2\u9ed1\u6811\u8fdb\u884c\u5b58\u50a8\u3002<\/li>\n<li><strong>\u67e5\u8be2\u65f6\u95f4\u590d\u6742\u5ea6<\/strong>\uff1a\u4eceJDK1.7\u7684\u904d\u5386\u94fe\u8868O(n)\uff0c JDK1.8 \u53d8\u6210\u904d\u5386\u7ea2\u9ed1\u6811O(logN)\u3002<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"ConcurrentHashMap\u5f31\u4e00\u81f4\u7684\u8fed\u4ee3\u5668\u7684\u539f\u7406\u662f\uff1aConcurrentHashMap \u7684\u5f31\u4e00\u81f4\u6027\u8fed\u4ee3\u5668 [&hellip;]","protected":false},"author":1,"featured_media":26717,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[37],"tags":[119],"acf":[],"_links":{"self":[{"href":"https:\/\/docs.pingcode.com\/wp-json\/wp\/v2\/posts\/26713"}],"collection":[{"href":"https:\/\/docs.pingcode.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/docs.pingcode.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/docs.pingcode.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/docs.pingcode.com\/wp-json\/wp\/v2\/comments?post=26713"}],"version-history":[{"count":0,"href":"https:\/\/docs.pingcode.com\/wp-json\/wp\/v2\/posts\/26713\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/docs.pingcode.com\/wp-json\/wp\/v2\/media\/26717"}],"wp:attachment":[{"href":"https:\/\/docs.pingcode.com\/wp-json\/wp\/v2\/media?parent=26713"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/docs.pingcode.com\/wp-json\/wp\/v2\/categories?post=26713"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/docs.pingcode.com\/wp-json\/wp\/v2\/tags?post=26713"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}