关于 sync.Map.Range 源码

来源:13-3 实现SyncDict(二)

弦歌ty

2022-06-21

老师,请问一下,Range 源码中的 read.amended 是什么意思,是用来确定 map 是否可以用吗?这个注释没太看懂,以及为什么要两次确认 read.amended?

func (m *Map) Range(f func(key, value any) bool) {
	// We need to be able to iterate over all of the keys that were already
	// present at the start of the call to Range.
	// If read.amended is false, then read.m satisfies that property without
	// requiring us to hold m.mu for a long time.
	read, _ := m.read.Load().(readOnly)
	if read.amended {
		// m.dirty contains keys not in read.m. Fortunately, Range is already O(N)
		// (assuming the caller does not break out early), so a call to Range
		// amortizes an entire copy of the map: we can promote the dirty copy
		// immediately!
		m.mu.Lock()
		read, _ = m.read.Load().(readOnly)
		if read.amended {
			read = readOnly{m: m.dirty}
			m.read.Store(read)
			m.dirty = nil
			m.misses = 0
		}
		m.mu.Unlock()
	}

	for k, e := range read.m {
		v, ok := e.load()
		if !ok {
			continue
		}
		if !f(k, v) {
			break
		}
	}
}
写回答

1回答

Moody

2022-06-21

amended这个在4-7和4-8应该是提到过,指的是read有没有被追加,如果是true的话,代表read里面并不是完整的数据,dirty里面有新数据。

这个地方确认两次,是为了防止m.mu.Lock()等待加锁时,dirty做了提升,这样dirty就空了,amended也变为false了。

0
0

深入Go底层原理,重写Redis中间件实战

深入Go语言原理+Go重写Redis

474 学习 · 172 问题

查看课程