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
相关产品推荐
相关产品推荐

