Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use Go sync.Map

2025-03-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article mainly explains "how to use Go sync.Map". The content in the article is simple and clear, and it is easy to learn and understand. Please follow the editor's train of thought to study and learn how to use Go sync.Map.

The following code, which seems to make a lot of sense, is actually used incorrectly (background: getting registration information in a concurrent scenario).

Instance, ok: = instanceMap [name] if ok {return instance, nil} initLock.Lock () defer initLock.Unlock () / / double checkinstance, ok = instanceMap [name] if ok {return instance, nil}

It makes more sense to use sync.Map here, because the underlying layer of sync.Map completely contains this logic. The students who wrote Java may look familiar with the above code, but they did use it incorrectly. Please pay attention to the following articles about why you used it incorrectly and what impact it will cause.

I probably analyzed the reasons why people would rather use Mutex + Map than sync.Map:

Sync.Map is inherently difficult to use and does not use like a Map. Lost the privileged syntax that map should have, such as make, map [1], etc.

There are many sync.Map methods. Making a simple Map easy to use has a higher learning cost.

Whatever the reason, after reading this article, it is recommended to use sync.Map instead of Map + Mutex in certain concurrency scenarios.

Usage complete solution package mainimport ("fmt"sync") func main () {var syncMap sync.Map syncMap.Store ("11", 11) syncMap.Store ("22", 22) fmt.Println (syncMap.Load ("11")) / / 11 fmt.Println (syncMap.Load ("33")) / / empty fmt.Println (syncMap.LoadOrStore ("33") ) / 33 fmt.Println (syncMap.Load ("33")) / / 33 fmt.Println (syncMap.LoadAndDelete ("33")) / / 33 fmt.Println (syncMap.Load ("33")) / / empty syncMap.Range (func (key, value interface {}) bool {fmt.Printf ("key:%v value:%v\ n", key, value) return true}) / / key:22 value:22 / / key:11 value:11}

In fact, sync.Map is not complicated, it just transforms the related operations of ordinary map into corresponding functions.

Ordinary mapsync.Mapmap gets a keymap [1] sync.Load (1) map add element map [1] = 10sync.Store (1,10) map deletes a keydelete (map, 1) sync.Delete (1) traverses mapfor...rangesync.Range ()

Sync.Map are two unique functions, but you can literally understand what they mean. Return if LoadOrStore:sync.Map exists, insert LoadAndDelete:sync.Map to get a key if it doesn't exist, and delete the key if it exists.

Source code parsing type Map struct {mu Mutex read atomic.Value / / readOnly read map dirty map [interface {}] * entry / / dirty map misses int}

Sync map panorama

Load

Store

Delete

When was the value of read map updated?

In the case of Load/LoadOrStore/LoadAndDelete, when the number of misses is greater than or equal to the number of elements of dirty map, dirty map is copied to read map as a whole

When Store/LoadOrStore, when the key exists in the read map, update the

When Delete/LoadAndDelete, if the key exists in read map, set this value to nil

When was the value of dirty map updated?

It is a completely new key. If you insert sync.Map for the first time, you must insert dirty map first.

In the case of Store/LoadOrStore, when the key does not exist in read map and the key exists in dirty map, update

In the case of Delete/LoadAndDelete, if the key does not exist in read map and the key exists in dirty map, then delete the key from dirty map

When the number of misses is greater than or equal to the number of elements of dirty map, dirty map is copied to read map as a whole, and dirty map is set to nil

Question: when dirty map is copied to read map, set dirty map to nil, that is, the key does not exist in dirty map. If you insert a new key and meet the condition of replicating from dirty map to read map after multiple visits, if you directly overwrite dirty map with read map, won't you lose the key that was in read map but not in dirty map?

A: actually, it won't. When dirty map is copied to read map, readOnly.amended equals false. When a new value is inserted, the value in read map will be re-assigned to dirty map, that is, read map will also be copied to dirty map.

Func (m * Map) dirtyLocked () {if m.dirty! = nil {return} read, _: = m.read.Load (). (readOnly) m.dirty = make (map [interface {}] * entry, len (read.m)) for k, e: = range read.m {if! e.tryExpungeLocked () {m.dirty [k] = e}} read map and dirty map were deleted?

When a key exists in the read map, only the read map is deleted, not the dirty map (because the dirty map does not exist)

When the read map does not exist, the value in dirty map will be deleted.

Question: if you delete it in this way, won't there be residual key in dirty map, which will not be deleted?

A: actually, it won't. When the number of misses is greater than or equal to the number of elements of dirty map, dirty map is copied to read map as a whole. This process comes with another operation: set dirty map to nil.

Func (m * Map) missLocked () {m.missesystems + if m.misses < len (m.dirty) {return} m.read.Store (readOnly {m: m.dirty}) m.dirty = nil m.misses = 0} the relationship between read map and dirty map?

Values that exist in read map may not exist in dirty map.

Values that exist in dirty map may also exist in read map.

When the number of misses is greater than or equal to the number of elements of dirty map, dirty map will be copied to read map as a whole when it is found that it exists in dirty map and does not exist in read map.

When dirty map is replicated to read map, dirty map is set to nil.

When dirty map replicates to read map, readOnly.amended equals false. When a new value is inserted, the value in read map will be re-assigned to dirty map.

Does the value in read/dirty map have to be valid?

Not necessarily. There are always three types of values that are put into read/dirty map:

Nil: if the obtained value is nil, the key has been deleted. Neither in read map nor in dirty map

Expunged: this key does not exist in dirty map

Valid: normally, either this value exists in read map or in dirty map

How does sync.Map improve performance?

Through the source code parsing, we know that there are two ordinary map,read map in sync.Map that are mainly responsible for reading, and dirty map is responsible for reading and writing (locking). In the scenario of reading more and writing less, the value of read map is basically unchanged, and read map can be operated without locks, thus reducing the locking / unlocking links necessary to use Mutex + Map, thus improving performance.

However, you can also see that read map can change, and if some key writes are particularly frequent, sync.Map will basically degenerate into Mutex + Map (it may not perform as well as Mutex + Map).

Therefore, it is not necessarily that the use of sync.Map can improve program performance, we try to pay attention to split granularity in our daily use to use sync.Map.

You can also use pprof on how to analyze whether sync.Map optimizes program performance. For the specific process, please refer to "this is probably the easiest to understand Go Mutex source code analysis"

Sync.Map application scenario

Read more and write less

There are also many writes, but the modified key does not coincide with the read key.

I think it's crazy about the second point. after all, it's hard for us to control it, but it's still here because it's an official comment.

In actual development, we should pay attention to the use of scenarios and the use of pprof to analyze program performance.

Pay attention to the use of sync.Map

Like Mutex, sync.Map cannot be copied because atomic.Value cannot be copied.

Thank you for your reading, the above is the content of "how to use Go sync.Map", after the study of this article, I believe you have a deeper understanding of how to use Go sync.Map, and the specific use needs to be verified in practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report