You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go语言sync.Map的Load等方法是否具备原子性?附示例疑问

关于Go sync.Map方法原子性及临界区互斥的解答

嘿,我来帮你把这两个问题讲清楚:

一、sync.Map核心方法的原子性

Go标准库的sync.Map是专门为并发安全场景设计的映射结构,它的Load、Store、LoadOrStore、Delete这几个方法全部具备原子性。

内部实现上,sync.Map 结合了原子操作(针对只读的"干净"数据)和互斥锁(针对需要修改的"脏"数据)来保证每个方法的执行都是不可分割的:

  • 单个方法的执行过程中,不会被其他goroutine的同类型操作打断
  • 比如LoadOrStore会原子性地完成「检查键是否存在→不存在则存储值」的整个流程,绝对不会出现多个goroutine同时判定键不存在并执行存储的情况

二、你的示例代码的临界区保证

先把你的示例代码还原出来:

package main

import (
	"fmt"
	"sync"
	"time"
)

var sm sync.Map

func main() {
	var wg sync.WaitGroup
	for i := 0; i < 10; i++ {
		wg.Add(1)
		go func(n int) {
			defer wg.Done()
			val, loaded := sm.LoadOrStore("key", "value")
			if !loaded {
				// 你关注的第15-17行代码段
				fmt.Printf("goroutine %d: 初始化key\n", n)
				time.Sleep(2 * time.Second)
				fmt.Printf("goroutine %d: 初始化完成\n", n)
			} else {
				fmt.Printf("goroutine %d: key已存在,值为%s\n", n, val)
			}
		}(i)
	}
	wg.Wait()
}

你的测试结果完全符合预期,这段代码确实能保证同一时刻只有一个goroutine进入第15-17行的代码段——甚至更进一步,从始至终只会有一个goroutine进入这段代码:

  • LoadOrStore的原子性保证了10个goroutine中只有第一个成功执行存储操作的goroutine会得到loaded=false的结果
  • 其他所有goroutine都会直接得到loaded=true,进入else分支,根本不会触及你标记的代码段
  • 所以完全不存在多个goroutine并发进入该代码段的可能

内容的提问来源于stack exchange,提问作者lnshi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:38:42