Does using a range not associated with a stream in Go get the value?

When changing a card m that has parallel records, including those that can be deleted from the card, is it safe to stream ?:

 for k, v := range m { ... } 

I think that for thread safety, I need other possible authors to not change the value of v while I am reading it, and (when using the mutex and because locking is a separate step), make sure that key k is still on the map. For instance:

 for k := range m { m.mutex.RLock() v, found := m[k] m.mutex.RUnlock() if found { ... // process v } } 

(Suppose other authors block the entry m before changing v .) Is there a better way?

Edit to add: I know that cards are not thread safe. However, they are thread safe in one direction, according to the Go specification at http://golang.org/ref/spec#For_statements (search "If map entries have not yet been deleted during the iteration"). This page shows that code using range does not have to worry about other goroutines inserting or removing from the map. My question is that this thread safety extends to v , so that I can get v to be read only using only for k, v := range m and another thread protected mechanism? I created some test code to try to cause the application to crash, to prove that it does not work, but even obviously unsafe code works (many goroutines violently change the same value of the card without a lock mechanism in place). I could not get Go to crash!

+6
source share
2 answers

No, card operations are not atomic / thread- oriented , as the commentator pointed out your frequently asked question golang "Why are card operations not defined as atomic?" ,

To ensure you have access to it, you are advised to use Go channels as a means of accessing resources . The channel is used for simple token transfer. Anyone who wants to change it will request this from the channel - blocking or non-blocking. Upon completion of work with the card, it transfers the token back to the channel.

Iterations and work with the map should be quite simple and short, so you should use only one token for full access.

If this is not the case, and you use the card for more complex things / the resource consumer needs more time, you can implement the reader- vs writer-access-token token. Thus, at any given time, only one writer can access the map, but when no writer is active, the token is transferred to any number of readers who will not change the map (thus, they can read at the same time).

For channels, see the Effective Go Channel Documentation .

+9
source

You can use concurrent-map to handle concurrency efforts for you.

 // Create a new map. map := cmap.NewConcurretMap() // Add item to map, adds "bar" under key "foo" map.Add("foo", "bar") // Retrieve item from map. tmp, ok := map.Get("foo") // Checks if item exists if ok == true { // Map stores items as interface{}, hence we'll have to cast. bar := tmp.(string) } // Removes item under key "foo" map.Remove("foo") 
0
source

Source: https://habr.com/ru/post/927955/


All Articles