Is it safe to read a function pointer at the same time without locking?

Suppose I have this:

go func() { for range time.Tick(1 * time.Millisecond) { a, b = b, a } }() 

And in another place:

 i := a // <-- Is this safe? 

For this question, it is immaterial that the value of i refers to the original a or b . The only question is whether reading a safe. That is, is it possible a be nil , partially assigned, invalid, undefined, ... anything other than a valid value?

I tried to do this with an error , but so far it has always succeeded (on my Mac).

I could not find anything specific outside of this quote in The Go Memory Model doc:

Reading and writing values ​​larger than one machine word behaves like several operations with the size of a machine word in an unspecified order.

Does this mean that one machine word write is efficiently atomic? And, if so, is a pointer to a function written in the "Jump" mode to one machine word?

Update: Here's a properly synchronized solution.

+5
source share
2 answers

Unsynchronized concurrent access to any variable from several goroutines, where at least one of them is undefined behavior by Go memory model .

Undefined means that it says: undefined. Perhaps your program will work correctly, it may work incorrectly. This can lead to memory loss and the type of security provided by Go runtime (see Example below). It can even crash your program. Or it can even lead to an explosion of the Earth (the probability that it is extremely small, maybe even less than 1e-40, but still ...).

This undefined in your case means that yes, i can be nil , partially assigned, invalid, undefined, ... nothing but a or b . This list is just a tiny subset of all the possible results.

Stop thinking that some data races (or may be) are benign or unhealthy. They can be a source of worse things if left unattended.

Since your code is written to the variable a in one goroutine and reads it in another goroutine (which tries to assign its value to another variable i ), this is a data race and, as such, it is unsafe. It doesn’t matter if your tests work "correctly." You can take your code as a starting point, expand / build on it and lead to disaster due to the initially “unhealthy” data race.

For related questions, read How Safe Are Golan Cards for Parallel Read / Write? and Wrong sync in go lang .

It is highly recommended that you read Dmitry Vyukov's blog post: Benign data: what could go wrong?

Also a very interesting blog post showing an example that violates Go memory security with intentional data arrangement: Golan race data for memory security breach

+9
source

In terms of race condition , it is unsafe. In short, my understanding of race conditions is that there are several asynchronous routines (coroutines, threads, processes, goroutines, etc.) trying to access the same resource, and at least one of them is an operation records, so in your example we have 2 goroutines reading and writing function type variables, I think it matters from the point of view of parallelism, these variables take place somewhere in the memory, and we are trying to read or write in this part of the memory .

Short answer: just run your example using the - race flag with go run -race or go build -race , and you will see the detected data race .

+3
source

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


All Articles