{"id":10006960,"date":"2022-12-14T17:04:48","date_gmt":"2022-12-14T09:04:48","guid":{"rendered":"https:\/\/ityet.com\/?p=10006960"},"modified":"2022-12-14T17:04:48","modified_gmt":"2022-12-14T09:04:48","slug":"%e7%9c%9f%e5%b8%8c%e6%9c%9b%e4%bd%a0%e4%b9%9f%e6%98%8e%e7%99%bdruntime-map%e5%92%8csync-map","status":"publish","type":"post","link":"https:\/\/itmax.cn\/?p=10006960","title":{"rendered":"\u771f\u5e0c\u671b\u4f60\u4e5f\u660e\u767druntime.Map\u548csync.Map"},"content":{"rendered":"<h2>Map \u5b98\u65b9\u4ecb\u7ecd<\/h2>\n<p>One of the most useful data structures in computer science is the hash table. Many hash table implementations exist with varying properties, but in general they offer fast lookups, adds, and deletes. Go provides a built-in map type that implements a hash table.<br \/>\u54c8\u5e0c\u8868\u662f\u8ba1\u7b97\u673a\u4e2d\u6700\u6709\u7528\u7684\u6570\u636e\u7ed3\u6784\u4e4b\u4e00\u3002\u63d0\u4f9b\u5feb\u901f\u67e5\u627e\u3001\u6dfb\u52a0\u548c\u5220\u9664\u3002 Go \u63d0\u4f9b\u4e86\u4e00\u4e2a\u5b9e\u73b0\u54c8\u5e0c\u8868\u7684\u5185\u7f6e Map \u7c7b\u578b\u3002<\/p>\n<h3>Hash \u51b2\u7a81<\/h3>\n<p>\u90a3\u5bf9\u4e8e Hash \u7684\u4e00\u4e2a\u6700\u91cd\u8981\u7684\u95ee\u9898\uff0c\u5c31\u662f hash \u51b2\u7a81\u3002\u4e0b\u9762\u6211\u4eec\u770b\u4e00\u4e0b\u5e38\u7528\u7684\u89e3\u51b3\u65b9\u6848\u3002<\/p>\n<h3>\u5f00\u653e\u5bfb\u5740\u6cd5<\/h3>\n<p>\u5f00\u653e\u5bfb\u5740\u6cd5\u60f3\u8c61\u6210\u4e00\u4e2a\u505c\u8f66\u95ee\u9898\u3002\u82e5\u5f53\u524d\u8f66\u4f4d\u5df2\u7ecf\u6709\u8f66\uff0c\u5219\u7ee7\u7eed\u5f80\u524d\u5f00\uff0c\u76f4\u5230\u627e\u5230\u4e00\u4e2a\u7a7a\u505c\u8f66\u4f4d\u3002<br \/><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000043048619\" alt=\"go-32-001\" title=\"go-32-001\" loading=\"lazy\"><\/p>\n<p>\u4e0a\u56fe\uff0c\u6bcf\u4e2a\u65b9\u683c\u5b50\uff0c\u5c31\u662f\u4e00\u4e2a\u8f66\u4f4d\uff0c\u5f53\u4e00\u8f86\u8f66\u6765\u7684\u65f6\u5019\uff0c\u4f1a\u4f9d\u6b21\u67e5\u8be2\u662f\u5426\u6709\u7a7a\u4f4d\uff0c\u5982\u679c\u6ca1\u6709\uff0c\u5219\u7ee7\u7eed\u5411\u540e\u9762\u627e\uff0c\u5982\u679c\u53d1\u73b0\u7a7a\u4f4d\u7f6e\uff0c\u5c31\u4f1a\u505c\u5230\u7a7a\u4f4d\u7f6e\u4e2d\u3002<\/p>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000043048620\" alt=\"go-32-002\" title=\"go-32-002\" loading=\"lazy\"><\/p>\n<p>\u4e0b\u9762\u770b\u4e00\u4e0b\uff0c\u6211\u4eec\u7684\u4ee3\u7801\u662f\u5982\u4f55\u5b9e\u73b0\u7684\uff1f<\/p>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000043048621\" alt=\"go-32-003\" title=\"go-32-003\" loading=\"lazy\"><\/p>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000043048622\" alt=\"go-32-004\" title=\"go-32-004\" loading=\"lazy\"><\/p>\n<ol>\n<li>m[&#8220;\u9762\u5411\u52a0\u85aa\u5b66\u4e60&#8221;]=&#8221;\u4ece 0 \u5230 Go \u8bed\u8a00\u5fae\u670d\u52a1\u67b6\u6784\u5e08-\u8bad\u7ec3\u8425&#8221;<\/li>\n<li>\u8981\u5bf9\u952e-&#8220;\u9762\u5411\u52a0\u85aa\u5b66\u4e60&#8221;\uff0c\u8fdb\u884c hash<\/li>\n<li>\u62ff\u5230\u5168\u4f53\u683c\u5b50\u7684\u603b\u6570\uff0c\u7136\u540e\u53d6\u6a21<\/li>\n<li>\u5982\u679c\u53d6\u6a21\u53d1\u73b0\u662f\u4f4d\u5b50 1\uff0c\u4f46\u662f\u53d1\u73b0 1 \u5df2\u7ecf\u88ab\u522b\u4eba\u5360\u4e86\uff0c\u90a3\u4e48\u5c31\u5411\u540e\u8d70\uff0c\u76f4\u5230\u6709\u7a7a\u4f4d\uff0c\u518d\u628a\u81ea\u5df1\u653e\u8fdb\u53bb\u3002<\/li>\n<\/ol>\n<p>\u770b\u4e86\u4e0a\u9762\u7684\u6b65\u9aa4\u662f\u4e0d\u662f\u548c\u505c\u8f66\uff0c\u662f\u4e00\u4e2a\u9053\u7406\uff1f<\/p>\n<p>\u90a3\u6211\u4eec\u518d\u770b\uff0c\u5982\u679c\u60f3\u8bfb\u53d6\u6570\u636e\u7684\u65f6\u5019:<\/p>\n<ol>\n<li>\u540c\u6837\u5bf9 J \u952e\u8fdb\u884c hash<\/li>\n<li>\u62ff\u5230\u5168\u4f53\u683c\u5b50\u7684\u603b\u6570\uff0c\u7136\u540e\u53d6\u6a21<\/li>\n<li>\u627e\u5230\u4f4d\u7f6e\u662f 1\uff0c\u4f46\u662f\u53d1\u73b0 key \u4e0d\u4e00\u6837\uff0c\u5b83\u53ef\u80fd\u5728\u540e\u9762\uff0c\u5c31\u4e00\u76f4\u5411\u540e\u67e5\u627e\u3002<\/li>\n<\/ol>\n<h3>\u62c9\u94fe\u6cd5<\/h3>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000043048623\" alt=\"go-32-005\" title=\"go-32-005\" loading=\"lazy\"><\/p>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000043048624\" alt=\"go-32-006\" title=\"go-32-006\" loading=\"lazy\"><\/p>\n<ol>\n<li>m[&#8220;\u9762\u5411\u52a0\u85aa\u5b66\u4e60&#8221;]=&#8221;\u4ece 0 \u5230 Go \u8bed\u8a00\u5fae\u670d\u52a1\u67b6\u6784\u5e08-\u8bad\u7ec3\u8425&#8221;<\/li>\n<li>\u8981\u5bf9\u952e-&#8220;\u9762\u5411\u52a0\u85aa\u5b66\u4e60&#8221;\uff0c\u8fdb\u884c hash<\/li>\n<li>\u627e\u5230\u5bf9\u5e94\u5230\u69fd\u4f4d\uff0c\u6bcf\u4e2a\u69fd\u4f4d\u5e76\u4e0d\u5b58\u50a8\u5177\u4f53\u6570\u636e\uff0c\u53ea\u662f\u4e00\u4e2a\u6307\u9488\uff0c\u5b83\u6307\u5411\u4e0b\u9762\u7684\u94fe\u8868<\/li>\n<li>\u5f53\u65b0\u589e\u6570\u636e\u7684\u65f6\u5019\uff0c\u4f1a\u628a\u6570\u636e\u6dfb\u52a0\u5230\u94fe\u8868\u5934\u90e8\uff08\u4e0a\u56fe\u4e2d\u9ec4\u8272\u5c0f\u7403\u4e3a\u4f8b\uff09<\/li>\n<\/ol>\n<h3>Go \u8bed\u8a00\u7684 Map<\/h3>\n<p>runtime\/map.go\uff0c\u770b\u5230 hmap \u8fd9\u4e2a\u7ed3\u6784\u4f53\uff0c\u5b83\u5c31 go \u8bed\u8a00\u7684 map<\/p>\n<pre><code class=\"go\">type hmap struct {\n    count     int\n    flags     uint8\n    B         uint8\n    noverflow uint16\n    hash0     uint32\n    buckets    unsafe.Pointer\n    oldbuckets unsafe.Pointer\n    nevacuate  uintptr\n    extra *mapextra\n}<\/code><\/pre>\n<ol>\n<li>count \u952e\u503c\u5bf9\u7684\u6570\u91cf<\/li>\n<li>B \u662f\u4ee5 2 \u4e3a\u5e95\uff0c\u6876\u4e2a\u6570\u7684\u5bf9\u6570<\/li>\n<li>hash0 hash \u7684\u79cd\u5b50<\/li>\n<li>oldbuckets \u65e7\u7684 hash \u6876<\/li>\n<li>buckets hash \u6876<\/li>\n<\/ol>\n<p>\u4e0b\u9762\u770b\u4e00\u4e2a Go \u8bed\u8a00\u7684\u54c8\u5e0c\u6876\u5177\u4f53\u957f\u4ec0\u4e48\u6837\uff1f\u7528 bmap \u7ed3\u6784\u4f53\u8868\u793a<\/p>\n<pre><code>bucketCntBits = 3\nbucketCnt     = 1 &lt;&lt; bucketCntBits\n\ntype bmap struct {\n    tophash [bucketCnt]uint8\n}<\/code><\/pre>\n<p>bucketCntBits \u4e00\u4e2a\u54c8\u5e0c\u6876\u53ef\u4ee5\u5b58\u653e\u6700\u5927\u7684 KV \u952e\u503c\u5bf9\u7684\u6570\u91cf<br \/>bucketCnt Hash \u6876\u7684\u6570\u91cf(\u5de6\u79fb 3 \u4f4d\uff0c\u4e5f\u5c31\u662f 8\u3002)<\/p>\n<pre><code>tophash [8]uint8<\/code><\/pre>\n<p>uint8 \u662f\u65e0\u7b26\u53f7\u7684 8 \u4e3a\u6570\u5b57\uff0c\u4e5f\u5c31\u662f 1 \u4e2a\u5b57\u8282\u3002 tophash \u662f\u5b58\u50a8\u6876\u4e2d\u7684\u6bcf\u4e2a\u952e\u7684\u54c8\u5e0c\u503c\u7684\u9876\u90e8\u5b57\u8282(1 \u4e2a\u5b57\u8282)\u3002\u540c\u6837\uff0ck \u548c v \u4e5f\u662f\u5bf9\u5e94\u7684 8 \u4e2a\u3002\u7136\u540e\u5728\u7f16\u8bd1\u7684\u65f6\u5019\uff0c\u5c06\u6240\u6709\u952e\u548c\u503c\u518d\u6253\u5305\uff0c\u8fd9\u6837\u5c31\u907f\u514d\u4e86\u5728 bmap \u4e2d\u56fa\u5b9a K \u548c V \u7684\u7c7b\u578b\uff0c\u6700\u540e\u8fd8\u6709\u4e00\u4e2a overflow \u7684\u6307\u9488\uff0c\u6307\u5411\u4e00\u4e2a\u6ea2\u51fa\u6876\u3002<\/p>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000043048625\" alt=\"go-32-007\" title=\"go-32-007\" loading=\"lazy\"><\/p>\n<p>\u65b0\u5efa Map<\/p>\n<pre><code class=\"go\">package main\n\nimport &quot;fmt&quot;\n\nfunc main() {\n    m := make(map[string]int, 16)\n}<\/code><\/pre>\n<p>16 \u4ee3\u8868\u9884\u8ba1\u8981\u6709 16 \u4e2a Key\uff0c\u5f53\u7136\u4f60\u4e5f\u53ef\u4ee5\u653e\u66f4\u591a\u7684 Key,Map \u4f1a\u6269\u5bb9\uff0c\u540e\u9762\u6211\u4eec\u4ecb\u7ecd\u5230\u3002<\/p>\n<p>\u4e0b\u9762\u5230\u547d\u4ee4\u884c\u6267\u884c go build -gcflags -S main.go<\/p>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000043048626\" alt=\"go-32-008\" title=\"go-32-008\" loading=\"lazy\"><\/p>\n<p>\u770b\u5230\u5b83\u8c03\u7528\u4e86 runtime.makemap \u8fd9\u4e2a\u51fd\u6570\u3002\u5230 runtime\/map.go \u4e2d\uff0c\u627e\u5230 makemap()\u51fd\u6570\u3002<\/p>\n<pre><code>func makemap(t *maptype, hint int, h *hmap) *hmap {\n    ...\n    if h == nil {\n        h = new(hmap)\n    }\n    h.hash0 = fastrand()\n\n    B := uint8(0)\n    for overLoadFactor(hint, B) {\n        B++\n    }\n    h.B = B\n}\n...\nh.buckets, nextOverflow = makeBucketArray(t, h.B, nil)\nif nextOverflow != nil {\n    h.extra = new(mapextra)\n    h.extra.nextOverflow = nextOverflow\n}\n...<\/code><\/pre>\n<p>4 \u884c \u65b0\u5efa hmap<br \/>6 \u884c \u83b7\u53d6 hash \u79cd\u5b50<br \/>9-11 \u884c \u8ba1\u7b97 B \u7684\u4e2a\u6570\uff0c\u6839\u636e\u521d\u59cb\u5316\u7684\u65f6\u5019\u4f20\u5165\u7684\u6570\u636e\u3002(make(map[string]int, 16) \u5c31\u662f\u8fd9\u4e2a\u6570\u5b57 16)<br \/>15 \u884c \u751f\u6210\u591a\u4e2a hash \u6876<br \/>16-19 \u884c \u751f\u6210\u6ea2\u51fa\u6876\uff0c\u5e76\u5b58\u653e\u5728.extra \u4e2d\uff0c\u5f53\u4e00\u4e2a\u6b63\u5e38\u7684 Bmap \u88c5\u6ee1\u6570\u636e\u540e\uff0c\u4f1a\u53bb\u5230 NextOverflow \u4e2d\u627e\u5230\u7a7a\u95f2\u7684\u6ea2\u51fa\u6876\uff0c\u56e0\u4e3a Bmap \u5b57\u6bb5\u4e2d\uff0c\u4e5f\u6709\u4e2a overflow \u7684\u6307\u9488\u3002\uff08\u4e5f\u5c31\u662f\u8bf4\uff0c\u4e00\u5f00\u59cb\u5148\u4fdd\u6301\u7a7a\u95f2\u6345\u7684\u6307\u9488\uff0c\u6bcf\u4e2a bmap \u6570\u636e\u4e5f\u4e0d\u591a\uff0c\u5f53\u54ea\u4e2a\u6876\u88c5\u6ee1\u4e86\uff0c\u5c31\u662f\u90a3\u4e2a\u6876\u7684 overflow \u6307\u9488\u6307\u5411\u539f\u6765\u95f2\u7f6e\u7684\u7684\u6ea2\u51fa\u6876\u5730\u5740\uff0c\u7136\u540e nextOverflow \u518d\u7ee7\u7eed\u6307\u5411\u4e0b\u4e00\u4e2a\u7a7a\u95f2\u7684\u6ea2\u51fa\u6876\uff0c\u4e5f\u5c31\u662f nextOverflow \u6c38\u8fdc\u6307\u5411\u4e0b\u4e00\u4e2a\u7a7a\u95f2\u7684\u6ea2\u51fa\u6876\uff0c\u7b49\u5f85\u7740\u54ea\u4e2a\u6345\u6ee1\u4e86\u9700\u8981\u65b0\u6876\u6765\u88c5\u6570\u636e\u4e86\uff0c\u518d\u901a\u8fc7\u90a3\u4e2a\u88c5\u6ee1\u6570\u636e\u6876\u7684 overflow \u6307\u5411\u8fd9\u4e2a\u6876\uff0c\u7136\u540e NextOverflow \u63a5\u7740\u79fb\u52a8\u6307\u9488\u6307\u5411\u65b0\u7a7a\u95f2\u6876\uff09<\/p>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000043048627\" alt=\"go-32-009\" title=\"go-32-009\" loading=\"lazy\"><\/p>\n<p>Map \u8bfb\u53d6\u6570\u636e<\/p>\n<p>1.\u8ba1\u7b97\u5728\u54ea\u4e2a\u6876\u91cc\uff1f<\/p>\n<p>Hash(&#8220;\u9505\u5305\u8089&#8221;+hash0)\uff0c\u5982\u679c\u751f\u6210\u7684\u4e8c\u8fdb\u5236\u662f 0110001101001011\uff0c\u5982\u679c\u6211\u4eec\u7684 HMap \u4e2d\u7684 B \u662f 3\uff0c\u90a3\u4e48\u672b\u5c3e\u53d6 3 \u4f4d 011\uff0c \u6362\u7b97\u6210\u5341\u8fdb\u5236\u5c31\u662f 3\uff0c\u5c31\u53ef\u4ee5\u62ff\u5230 buket 3,\u7531\u4e8e\u6570\u7ec4\u662f\u4ece 0 \u5f00\u59cb\uff0c\u6240\u4ee5\u4e5f\u5c31\u662f 4 \u53f7\u6876\u3002<\/p>\n<p>2.\u83b7\u53d6 TopHash<\/p>\n<p>\u83b7\u53d6\u4e8c\u8fdb\u5236\u524d 8 \u4f4d 01100011\uff0c\u6362\u7b97\u6210 16 \u4f4d\u662f 0x63<\/p>\n<p>3.\u904d\u5386 TopHash<\/p>\n<p>\u5230\u6570\u7ec4\u4e2d\u904d\u5386\uff0c\u770b\u770b\u54ea\u4e2a\u4f4d\u7f6e\u7684 tophash \u662f 0x63<\/p>\n<p>4.TopHash \u76f8\u540c<\/p>\n<p>\u7ee7\u7eed\u67e5\u770b key\uff0c\u5982\u679c\u76f8\u7b49\uff0c\u5c31\u8fd4\u56de\u5143\u7d20\uff0c\u5982\u679c\u4e0d\u76f8\u7b49\uff0c\u7ee7\u7eed\u5bf9\u6bd4\u67e5\u627e\u3002<\/p>\n<p>5.TopHash \u4e0d\u540c<\/p>\n<p>\u5982\u679c 4 \u53f7\u6876\u7684\u6570\u7ec4\u90fd\u904d\u5386\u5b8c\u4e86\uff0c\u6ca1\u6709 0x63 \u7684 tophash,\u5982\u679c\u6709\u6ea2\u51fa\u6876\uff0c\u90a3\u5c31\u518d\u53bb\u6ea2\u51fa\u6876\u4e2d\u67e5\u627e\u3002\u5982\u679c\u90fd\u6ca1\u6709\u627e\u5230\uff0c\u90a3\u5c31\u662f\u627e\u4e0d\u5230 key \u6240\u5bf9\u5e94\u7684\u5143\u7d20\u3002<\/p>\n<p>Map \u5199\u6570\u636e<\/p>\n<p>1.\u627e\u5230\u5bf9\u5e94\u7684\u6876\uff08\u6876\u81ea\u8eab\u6216\u6ea2\u51fa\u6876\uff09<\/p>\n<p>2.\u627e\u5230\u5bf9\u5e94\u7684 key<\/p>\n<p>3.\u4fee\u6539\u6570\u636e\u7684\u503c<\/p>\n<p>4.\u5982\u679c\u8fd9\u4e2a\u6876\u91cc\u6ca1\u6709\u5bf9\u5e94\u7684 key,\u90a3\u4e48\u5c31\u76f4\u63a5\u63d2\u5165\u4e00\u4e2a<\/p>\n<h2>Map \u6269\u5bb9\u90fd\u505a\u4e86\u4ec0\u4e48\uff1f<\/h2>\n<pre><code>if !h.growing() &amp;&amp; (overLoadFactor(h.count+1, h.B) || tooManyOverflowBuckets(h.noverflow, h.B)) {\n    hashGrow(t, h)\n    ...\n}<\/code><\/pre>\n<p>\u53ef\u4ee5\u770b\u5230\u6709 2 \u4e2a\u6761\u4ef6\u53ef\u4ee5\u89e6\u53d1 Map \u7684\u6269\u5bb9<\/p>\n<ol>\n<li>\n<p>hmap \u4e0d\u5728\u589e\u52a0\u5e76\u4e14\u6ea2\u51fa\u56e0\u5b50\u5f88\u591a<\/p>\n<pre><code>func overLoadFactor(count int, B uint8) bool {\n     return count &gt; bucketCnt &amp;&amp; uintptr(count) &gt; loadFactorNum*(bucketShift(B)\/loadFactorDen)\n}<\/code><\/pre>\n<p>bucketCnt \u662f 8\uff0cloadFactorNum \u662f 13\uff0cloadFactorDen \u662f 2<\/p>\n<\/li>\n<li>\u592a\u591a\u7684\u6ea2\u51fa\u6876\uff08\u8fd9\u4e2a\u4f1a\u5f62\u6210\u975e\u5e38\u957f\u7684\u94fe\u8868\uff0c\u5bfc\u81f4\u4e25\u91cd\u7684\u6027\u80fd\u4e0b\u964d\uff09<\/li>\n<\/ol>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000043048628\" alt=\"go-32-010\" title=\"go-32-010\" loading=\"lazy\"><\/p>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000043048629\" alt=\"go-32-011\" title=\"go-32-011\" loading=\"lazy\"><\/p>\n<p>\u770b\u4e00\u4e0b\u4ee3\u7801<\/p>\n<pre><code>func hashGrow(t *maptype, h *hmap) {\n    ...\n    oldbuckets := h.buckets\n    newbuckets, nextOverflow := makeBucketArray(t, h.B+bigger, nil)\n    ...\n    h.B += bigger\n    h.flags = flags\n    h.oldbuckets = oldbuckets\n    h.buckets = newbuckets\n    if h.extra != nil &amp;&amp; h.extra.overflow != nil {\n        ...\n    }\n}<\/code><\/pre>\n<ul>\n<li>3 \u884c \u628a\u539f\u6765\u7684\u6876\u7ed9 oldbuckets<\/li>\n<li>4 \u884c h.B+bigger \u8fdb\u884c\u521b\u5efa\u65b0\u6876\u548c\u6ea2\u51fa\u6876<\/li>\n<li>6 \u884c \u66f4\u65b0 B \u7684\u503c<\/li>\n<li>7 \u884c \u66f4\u65b0 flags<\/li>\n<li>8 \u884c \u628a oldbuckets \u7ed9 h.oldbuckets<\/li>\n<li>9 \u884c \u628a newbuckets \u7ed9 h.buckets<\/li>\n<li>10 \u884c \u6ea2\u51fa\u6876\u5982\u679c\u4e0d\u4e3a\u7a7a\uff0c\u66f4\u65b0\u65b0\u6876\u7684\u6ea2\u51fa\u6876<\/li>\n<\/ul>\n<p>\u6b64\u65f6\uff0c\u65b0\u6876\u548c\u8001\u6876\u90fd\u5b58\u5728\uff0c\u8fd8\u6ca1\u6d89\u53ca\u5230\u6570\u636e\u8fc1\u79fb\u7684\u95ee\u9898\uff0c\u4e0b\u9762\u6211\u4eec\u770b<br \/>Hash(\u201c\u9505\u5305\u8089\u201d+hash0)\uff0c\u5982\u679c\u751f\u6210\u7684\u4e8c\u8fdb\u5236\u662f 0110001101001011\uff0c\u5982\u679c\u6211\u4eec\u7684 HMap \u4e2d\u7684 B \u662f 1\uff0c\u90a3\u4e48\u672b\u5c3e\u53d6 1 \u4f4d 1\uff0c \u6362\u7b97\u6210\u5341\u8fdb\u5236\u5c31\u662f 1\uff0c\u73b0\u5728\u6269\u5bb9\uff0cB \u662f 2\uff0c\u672b\u5c3e\u53d6 2 \u4f4d\uff0c\u5c31\u662f 11\uff0c\u6362\u7b97\u5341\u8fdb\u5236\u5c31\u662f 3\uff0c\u4e5f\u5c31\u662f\u8bf4\uff0c\u672a\u6765\u6570\u636e\u4f1a\u5206\u914d\u5230 buket-1 \u548c buket-3 \u4e0a\u3002<br \/>\u63a5\u4e0b\u6765\u770b\u5982\u4f55\u5904\u7406\u6570\u636e<\/p>\n<pre><code>func growWork(t *maptype, h *hmap, bucket uintptr) {\n    evacuate(t, h, bucket&amp;h.oldbucketmask())\n\n    \/\/ evacuate one more oldbucket to make progress on growing\n    if h.growing() {\n        evacuate(t, h, h.nevacuate)\n    }\n}<\/code><\/pre>\n<p>growWork()\u5c06\u65e7\u6876\u4e0a\u7684\u6570\u636e\u653e\u5230\u65b0\u6876\u4e2d\u53bb\u3002<\/p>\n<p>\u6570\u636e\u8fc1\u79fb\u5b8c\u6210\u540e\uff0c\u628a\u65e7\u6876\u7ed9 GC \u4e86\u3002<\/p>\n<h2>Map \u662f\u5e76\u53d1\u5b89\u5168\u7684\u5417\uff1f<\/h2>\n<p>\u57fa\u4e8e\u4e0a\u9762\u7684\u5b66\u4e60\uff0c\u6211\u4eec\u4e5f\u53ef\u4ee5\u770b\u5230 \u6269\u5bb9\u524d\u548c\u6269\u5bb9\u540e\uff0c \u5f53\u65e7\u6876\u548c\u65b0\u6876\u540c\u65f6\u5b58\u5728\u7684\u65f6\u5019\uff0c\u5c0f\u660e\u53d1\u8d77\u8bfb\u6570\u636e\uff0c\u5c0f\u521a\u53d1\u8d77\u5199\u6570\u636e\uff0c\u5c0f\u521a\u5c31\u4f1a\u8fdb\u5165\u65e7\u6876\uff0c\u8fdb\u884c\u6570\u636e\u8fc1\u79fb\uff0c\u90a3\u4e48\u5c0f\u660e\u5f88\u6709\u53ef\u80fd\u5728\u8bfb\u53d6\u7684\u65f6\u5019\uff0c\u65e7\u6876\u7684\u6570\u636e\u5df2\u7ecf\u88ab\u8fc1\u79fb\u5230\u4e86\u65b0\u6876\u4e2d\uff0c\u8fd9\u6837\u6570\u636e\u5c31\u4f1a\u8bfb\u9519\u4e71\u3002<\/p>\n<p>\u4e0b\u9762\u770b\u4e00\u4e0b Snyc.Map\uff08\u6ce8:\u4e0a\u9762\u7684 map \u662f runtime \u5305\u4e0b\u7684\uff09<\/p>\n<pre><code>type Map struct {\n    mu Mutex\n    read atomic.Value \/\/ readOnly\n    dirty map[any]*entry\n    misses int\n}\n\ntype readOnly struct {\n    m map[any]*entry\n    amended bool\n}\n\ntype entry struct {\n    p unsafe.Pointer \/\/ *interface{}\n}<\/code><\/pre>\n<ul>\n<li>2 \u884c mu \u662f\u4e00\u4e2a\u9501<\/li>\n<li>8-11 \u884c read \u5bf9\u5e94 readOnly \u7684\u7ed3\u6784\u4f53\uff0creadOnly \u4e2d\u7684 m \u662f\u4e00\u4e2a\u4efb\u610f\u7c7b\u578b\u952e\u548c\u4efb\u610f\u7c7b\u578b\u503c\u7684 map\uff0centry \u662f\u5305\u542b\u4e00\u4e2a unsafe.Pointer \u7684\u6307\u9488 p \u7684\u7ed3\u6784\u4f53\u3002<\/li>\n<li>10 \u884c amended \u662f\u4fee\u6b63\u7684\u610f\u601d\u3002<\/li>\n<li>4 \u884c dirty \u662f\u4e00\u4e2a\u4efb\u610f\u7c7b\u578b\u952e\u548c\u4efb\u610f\u7c7b\u578b\u503c\u7684 map<\/li>\n<li>5 \u884c misses \u672a\u51fb\u4e2d<\/li>\n<\/ul>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000043048630\" alt=\"go-32-013\" title=\"go-32-013\" loading=\"lazy\"><\/p>\n<pre><code>func (m *Map) Store(key, value any) {\n    read, _ := m.read.Load().(readOnly)\n    if e, ok := read.m[key]; ok &amp;&amp; e.tryStore(&amp;value) {\n        return\n    }\n\n    m.mu.Lock()\n    read, _ = m.read.Load().(readOnly)\n    if e, ok := read.m[key]; ok {\n        if e.unexpungeLocked() {\n            m.dirty[key] = e\n        }\n        e.storeLocked(&amp;value)\n    } else if e, ok := m.dirty[key]; ok {\n        e.storeLocked(&amp;value)\n    } else {\n        if !read.amended {\n            m.dirtyLocked()\n            m.read.Store(readOnly{m: read.m, amended: true})\n        }\n        m.dirty[key] = newEntry(value)\n    }\n    m.mu.Unlock()\n}<\/code><\/pre>\n<p>\u4e0a\u9762\u5c31\u662f\u5b58\u50a8\u6570\u636e\u7684\u4ee3\u7801\u3002<\/p>\n<p>2-5 \u5982\u679c read \u4e2d\u4e2d\u53ef\u4ee5\u627e\u5230\u8fd9\u4e2a Key,\u5e76\u4e14\u6ca1\u6709\u88ab\u6807\u8bb0\u88ab\u5220\u9664\uff0c\u5c31 tryStore(),\u8bd5\u56fe\u53bb\u66f4\u65b0\u503c\u3002<\/p>\n<p>7-24 \u5982\u679c read \u4e2d\u4e0d\u5b58\u5728\u8fd9\u4e2a Key \u6216\u8005\u88ab\u6807\u8bb0\u4e3a\u5df2\u5220\u9664\u7684\u60c5\u51b5\uff0c\u6b64\u65f6\u52a0\u9501\/\u89e3\u9501\u3002<\/p>\n<p>9-13 \u518d\u6b21\u8bfb\u53d6 read,\u6b64\u65f6\u5df2\u7ecf\u627e\u5230\u4e86 Key,\u5982\u679c entry \u88ab\u5220\u9664\u4e86\uff0c\u90a3\u4e48\u5c31\u628a\u8fd9\u4e2a key \u548c value \u5b58\u50a8\u5230 dirty \u7684 map \u4e2d<\/p>\n<p>14-16 dirty \u7684 map \u4e2d\u5b58\u5728\u8fd9\u4e2a key\uff0c\u66f4\u65b0\u8fd9\u4e2a\u503c<\/p>\n<p>17 \u5230\u8fd9\u4e00\u6b65\uff0c\u8fd9\u4e2a\u5224\u65ad\u8bc1\u660e read \u548c dirty \u90fd\u6ca1\u6709\u8fd9\u4e2a key,\u5982\u679c read \u7684 amended \u4e3a\u5047\uff0c\u8bc1\u660e read \u548c dirty \u7684\u4e24\u4e2a map \u4e2d\u7684\u6570\u636e\u662f\u76f8\u7b49\u7684<\/p>\n<p>18 \u5982\u679c dirty \u662f nil\uff0c\u5c31\u628a read \u7684\u6570\u636e\u90fd\u653e\u5230 dirty \u4e2d\uff0c\u5426\u5219 dirty \u6709\u6570\u636e\uff0c\u5c31\u600e\u4e48\u90fd\u4e0d\u505a\uff0c\u76f4\u63a5\u8fd4\u56de\u3002<\/p>\n<p>19 \u6807\u8bb0 amended \u4e3a true,\u8bc1\u660e read \u548c dirty \u4e0d\u540c\u4e86<\/p>\n<p>21 \u628a\u6570\u636e\u653e\u5230 dirty \u7684 map \u4e2d\u3002<\/p>\n<p>\u5355\u534f\u7a0b\u4ee3\u7801\u6f14\u793a<\/p>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000043048631\" alt=\"go-32-012\" title=\"go-32-012\" loading=\"lazy\"><\/p>\n<p>\u4e0a\u56fe\uff0c\u4ece goland \u4e2d\u6253\u5370\u51fa\u6765\u7684\u6d88\u606f\u770b\uff0c\u6570\u636e\u90fd\u5728 dirty \u7684 map \u4e2d\u3002<\/p>\n<pre><code>func (m *Map) Load(key any) (value any, ok bool) {\n    read, _ := m.read.Load().(readOnly)\n    e, ok := read.m[key]\n    if !ok &amp;&amp; read.amended {\n        m.mu.Lock()\n        read, _ = m.read.Load().(readOnly)\n        e, ok = read.m[key]\n        if !ok &amp;&amp; read.amended {\n            e, ok = m.dirty[key]\n            m.missLocked()\n        }\n        m.mu.Unlock()\n    }\n    if !ok {\n        return nil, false\n    }\n    return e.load()\n}\n\nfunc (m *Map) missLocked() {\n    m.misses++\n    if m.misses &lt; len(m.dirty) {\n        return\n    }\n    m.read.Store(readOnly{m: m.dirty})\n    m.dirty = nil\n    m.misses = 0\n}<\/code><\/pre>\n<p>2-3 \u5230 read \u4e2d\u7684 map \u67e5\u627e key<\/p>\n<p>4-13 read \u4e2d\u6ca1\u627e\u5230\uff0c\u5e76\u4e14 amended \u4e3a\u771f\uff0c\u610f\u5473 read \u548c dirty,\u8fd9 2 \u4e2a map \u6570\u636e\u4e0d\u4e00\u81f4\u3002\uff08dirty \u7684\u6570\u636e\u901a\u5e38\u662f\u591a\u7684\uff09<\/p>\n<p>5-12 \u52a0\u9501\uff0c\u64cd\u4f5c dirty \u7684 map<\/p>\n<p>6-7 \u518d\u6b21\u8bfb\u53d6 map<\/p>\n<p>8 read \u4e2d\u4ecd\u7136\u627e\u4e0d\u5230\u8fd9\u4e2a key,\u5e76\u4e14 amended \u4e3a\u771f<\/p>\n<p>9 \u53bb dirty \u4e2d\u8bfb\u53d6\u8be5 key<\/p>\n<p>10 \u7ed9 misses +1\uff0c\u5982\u679c m.misses == len(m.dirty)\uff0c\u90a3\u4e48\u5c31\u628a m.dirty \u653e\u5230 read \u4e2d\u7684 m \u53d8\u91cf\u91cc\uff0c\u7136\u540e dirty \u8bbe\u7f6e nil\uff0cmisses \u8bbe\u7f6e\u4e3a 0<\/p>\n<p>14 read \u4e2d\u6ca1\u627e\u5230,\u4f46\u662f amended \u4e3a\u5047\uff0c\u8bf4\u660e read \u548c dirty \u6570\u636e\u76f8\u540c\uff0c\u6240\u4ee5\uff0c\u76f4\u63a5\u8fd4\u56de nil\uff0cfalse<\/p>\n<p>17 read \u4e2d\u627e\u5230\u4e86 entry,\u76f4\u63a5\u8c03\u7528 entry \u7684 load()\u65b9\u6cd5\u5c31\u53ef\u4ee5\u4e86<\/p>\n<pre><code>    var m sync.Map\n    num := 100\n    var w sync.WaitGroup\n    w.Add(num)\n    m.Store(&quot;\u300aGo\u8bed\u8a00\u6781\u7b80\u4e00\u672c\u901a\u300b\u7b2c4\u6b21\u5370\u5237&quot;, 1)\n    m.Store(&quot;\u300aGo\u8bed\u8a00\u5fae\u670d\u52a1\u67b6\u6784\u6838\u5fc322\u8bb2\u300b&quot;, 2)\n    m.Store(&quot;\u300aGo\u8bed\u8a00+Redis\u300b\u5b9e\u6218\u8bfe&quot;, 3)\n    m.Store(&quot;\u300aGo\u8bed\u8a00+RabbitMQ\u300b\u5b9e\u6218\u8bfe&quot;, 4)\n    m.Store(&quot;\u300a\u4ece0\u5230Go\u8bed\u8a00\u5fae\u670d\u52a1\u67b6\u6784\u5e08\u300b\u8bad\u7ec3\u8425&quot;, 5)\n    m.Store(&quot;\u300aWeb3\u4e0eGo\u8bed\u8a00\u300b\u5b9e\u6218\u8bfe&quot;, 6)\n\n    for i := 0; i &lt; num; i++ {\n        go func() {\n            v2, _ := m.Load(&quot;\u300aWeb3\u4e0eGo\u8bed\u8a00\u300b\u5b9e\u6218\u8bfe&quot;)\n            fmt.Println(v2)\n            w.Done()\n        }()\n    }\n    w.Wait()\n    fmt.Println(m)<\/code><\/pre>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000043048632\" alt=\"go-32-014\" title=\"go-32-014\" loading=\"lazy\"><\/p>\n<h4>\u5220\u9664\u65b9\u6cd5\u6e90\u4ee3\u7801\u5206\u6790<\/h4>\n<pre><code>func (m *Map) Delete(key any) {\n    m.LoadAndDelete(key)\n}\n\nfunc (m *Map) LoadAndDelete(key any) (value any, loaded bool) {\n    read, _ := m.read.Load().(readOnly)\n    e, ok := read.m[key]\n    if !ok &amp;&amp; read.amended {\n        m.mu.Lock()\n        read, _ = m.read.Load().(readOnly)\n        e, ok = read.m[key]\n        if !ok &amp;&amp; read.amended {\n            e, ok = m.dirty[key]\n            delete(m.dirty, key)\n            m.missLocked()\n        }\n        m.mu.Unlock()\n    }\n    if ok {\n        return e.delete()\n    }\n    return nil, false\n}<\/code><\/pre>\n<p>6-7 \u8bfb\u53d6 read \u4e2d\u7684 map \u7684 key<\/p>\n<p>8 \u5982\u679c\u6ca1\u627e\u5230\uff0c\u5e76\u4e14 amended \u4e3a\u771f\uff0c\u8bc1\u660e read \u548c dirty \u4e2d\u7684 map \u6570\u636e\u4e0d\u76f8\u7b49<\/p>\n<p>9-17 \u52a0\u9501\u64cd\u4f5c dirty \u7684 map<\/p>\n<p>10-12 \u518d\u6b21\u8bfb\u53d6 read \u4e2d\u7684 map,\u5982\u679c\u6ca1\u627e\u5230\uff0c\u5e76\u4e14 amended \u4e3a\u771f<\/p>\n<p>13 \u67e5\u627e dirty \u7684 map \u4e2d key<\/p>\n<p>14 \u5220\u9664 dirty \u7684 map \u4e2d key<\/p>\n<p>15 \u5224\u65ad\u662f\u5426\u628a dirty \u7684 map \u63d0\u5347\u5230 read \u4e2d\u53bb<\/p>\n<p>19-20 \u5728 read \u4e2d\u627e\u5230\u4e86 entry\uff0c\u90a3\u4e48\u5c31\u76f4\u63a5\u8c03\u7528 entry \u7684 delete()<\/p>\n<p>\u5728 main \u534f\u7a0b\u5185\uff0c\u6267\u884c\u5220\u9664\u64cd\u4f5c<\/p>\n<pre><code>    var m sync.Map\n    m.Store(&quot;\u300aGo\u8bed\u8a00\u6781\u7b80\u4e00\u672c\u901a\u300b\u7b2c4\u6b21\u5370\u5237&quot;, 1)\n    m.Store(&quot;\u300aGo\u8bed\u8a00\u5fae\u670d\u52a1\u67b6\u6784\u6838\u5fc322\u8bb2\u300b&quot;, 2)\n    m.Store(&quot;\u300aGo\u8bed\u8a00+Redis\u300b\u5b9e\u6218\u8bfe&quot;, 3)\n    m.Store(&quot;\u300aGo\u8bed\u8a00+RabbitMQ\u300b\u5b9e\u6218\u8bfe&quot;, 4)\n    m.Store(&quot;\u300a\u4ece0\u5230Go\u8bed\u8a00\u5fae\u670d\u52a1\u67b6\u6784\u5e08\u300b\u8bad\u7ec3\u8425&quot;, 5)\n    m.Store(&quot;\u300aWeb3\u4e0eGo\u8bed\u8a00\u300b\u5b9e\u6218\u8bfe&quot;, 6)\n    m.Delete(&quot;\u300aWeb3\u4e0eGo\u8bed\u8a00\u300b\u5b9e\u6218\u8bfe&quot;)\n    fmt.Println(m)<\/code><\/pre>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000043048633\" alt=\"go-32-015\" title=\"go-32-015\" loading=\"lazy\"><\/p>\n<p>\u591a\u534f\u7a0b\u5220\u9664\u64cd\u4f5c<\/p>\n<pre><code>    var m sync.Map\n    num := 100\n    var w sync.WaitGroup\n    w.Add(num)\n    m.Store(&quot;\u300aGo\u8bed\u8a00\u6781\u7b80\u4e00\u672c\u901a\u300b\u7b2c4\u6b21\u5370\u5237&quot;, 1)\n    m.Store(&quot;\u300aGo\u8bed\u8a00\u5fae\u670d\u52a1\u67b6\u6784\u6838\u5fc322\u8bb2\u300b&quot;, 2)\n    m.Store(&quot;\u300aGo\u8bed\u8a00+Redis\u300b\u5b9e\u6218\u8bfe&quot;, 3)\n    m.Store(&quot;\u300aGo\u8bed\u8a00+RabbitMQ\u300b\u5b9e\u6218\u8bfe&quot;, 4)\n    m.Store(&quot;\u300a\u4ece0\u5230Go\u8bed\u8a00\u5fae\u670d\u52a1\u67b6\u6784\u5e08\u300b\u8bad\u7ec3\u8425&quot;, 5)\n    m.Store(&quot;\u300aWeb3\u4e0eGo\u8bed\u8a00\u300b\u5b9e\u6218\u8bfe&quot;, 6)\n\n    for i := 0; i &lt; num; i++ {\n        go func() {\n            m.Delete(&quot;\u300aWeb3\u4e0eGo\u8bed\u8a00\u300b\u5b9e\u6218\u8bfe&quot;)\n            w.Done()\n        }()\n    }\n    w.Wait()\n    fmt.Println(m)<\/code><\/pre>\n<p><a href=\"https:\/\/segmentfault.com\/a\/1190000043048617\">https:\/\/segmentfault.com\/a\/1190000043048617<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Map \u5b98\u65b9\u4ecb\u7ecd One of the most useful data structures in comp [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[4],"tags":[],"class_list":["post-10006960","post","type-post","status-publish","format-standard","hentry","category-share"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts\/10006960","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=10006960"}],"version-history":[{"count":0,"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts\/10006960\/revisions"}],"wp:attachment":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=10006960"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=10006960"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=10006960"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}