Topology diagram of sync.Map
Some key points to understand the diagram
var expunged = unsafe.Pointer(new(interface{})) type Map struct type readOnly struct type entry struct func (m *Map) Load(key interface{}) (value interface{}, ok bool) func (m *Map) Store(key, value interface{}) func (m *Map) Delete(key interface{}) func (m *Map) Range(f func(key, value interface{}) bool)
Here, we should focus on the numerical states of readonly. Ameded, Map.misses and entry.p. in the topological diagram, many points are used to judge the trend
Next, the code and notes of the structure are listed in detail for the convenience of reading and understanding the topology map
Main structure and comments of sync.Map
type Map struct { //Mutex, used to lock dirty map mu Mutex //Read map first and support atomic operation. If there is readOnly in the annotation, it doesn't mean read is read-only, but its structure. Read actually has a write operation read atomic.Value // dirty is the latest map, which allows reading and writing dirty map[interface{}]*entry // It mainly records the number of times the read map and the dirty map cannot be read by the read. When the misses is equal to the length of the dirty, the dirty map will be copied to the read misses int } // readOnly is mainly used for storage, and elements are stored in Map.read through atomic operation. type readOnly struct { // map of read, used to store all read data m map[interface{}]*entry // If the data is in dirty but not in read, the value is true as the modification ID amended bool } // entry is the specific map value of Map.dirty type entry struct { // Nil: indicates that the element in read map can be set to nil by calling Delete() // Expunged: it also means that the key is deleted, but the key is only in read and not in dirty. This happens when you copy read to dirty. That is to say, in the process of copying, nil will be marked expunged first, and then it will not be copied to dirty // Other: indicates that there is real data p unsafe.Pointer // *interface{} }
The principle of sync.Map is very simple. The strategy of space for time is used. Through two redundant data structures (read and dirty), the effect of lock on performance is realized.
Two maps are introduced to separate reading and writing from each other. read map provides concurrent reading and atomic writing of existing elements, while dirty map is responsible for reading and writing.
In this way, the read map can be read concurrently without locking. When no value is read in the read map, the read map can be locked for subsequent reading, and the number of misses can be accumulated.
When the number of misses is greater than or equal to the length of the dirty map, the dirty map is raised to read map.
From the definition of the structure, we can see that although two map s are introduced, the underlying data stores pointers, pointing to the same value.
Reference documents:
sync.Map source code analysis you have to know