Go语言map是怎么比较key是否存在的

Python013

Go语言map是怎么比较key是否存在的,第1张

支持==!=操作做key实际function、map、slice三kind支持作key能nil比较能另值比较布尔、整型、浮点、复数、字符串、指针、channel等都做key struct能能做key要看每字段所字段都做keystruct字段能做keystruct能做keyarray元素类型能做keyarray 例: type Foo map[struct { B bool I int F float64 C complex128 S string P *Foo Ch chan Foo }]bool 每字段都做keyFoo做key再: type Foo map[struct { Fn func() Foo M map[*Foo]int S []Foo }]bool 字段能做key、Foo允许做key三字段都能 字段递归检查: type Foo map[struct { Sub struct { M map[*Foo]bool } }]bool SubM字段能做keySub能做keyFoo能做key 总想数据结构用于mapkey能包含function、mapslic

sync.Map是1.9才推荐的并发安全的map,除了互斥量以外,还运用了原子操作,所以在这之前,有必要了解下 Go语言——原子操作

go1.10\src\sync\map.go

entry分为三种情况:

从read中读取key,如果key存在就tryStore。

注意这里开始需要加锁,因为需要操作dirty。

条目在read中,首先取消标记,然后将条目保存到dirty里。(因为标记的数据不在dirty里)

最后原子保存value到条目里面,这里注意read和dirty都有条目。

总结一下Store:

这里可以看到dirty保存了数据的修改,除非可以直接原子更新read,继续保持read clean。

有了之前的经验,可以猜测下load流程:

与猜测的 区别

由于数据保存两份,所以删除考虑:

先看第二种情况。加锁直接删除dirty数据。思考下貌似没什么问题,本身就是脏数据。

第一种和第三种情况唯一的区别就是条目是否被标记。标记代表删除,所以直接返回。否则CAS操作置为nil。这里总感觉少点什么,因为条目其实还是存在的,虽然指针nil。

看了一圈貌似没找到标记的逻辑,因为删除只是将他变成nil。

之前以为这个逻辑就是简单的将为标记的条目拷贝给dirty,现在看来大有文章。

p == nil,说明条目已经被delete了,CAS将他置为标记删除。然后这个条目就不会保存在dirty里面。

这里其实就跟miss逻辑串起来了,因为miss达到阈值之后,dirty会全量变成read,也就是说标记删除在这一步最终删除。这个还是很巧妙的。

真正的删除逻辑:

很绕。。。。