-
Notifications
You must be signed in to change notification settings - Fork 18.1k
golang documents should make it clear whether or not reading/writing scalar type variables is atomic. #16048
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
"Atomic" is a very overloaded word in this context. What precisely do you mean? I think that the Go memory model, which you reference, already says what we want to say. It "specifies the conditions under which reads of a variable in one goroutine can be guaranteed to observe values produced by writes to the same variable in a different goroutine." I don't see a reason to be more specific. Your example program only tells you what happens on one particular machine on one particular implementation. Go is intentionally defined by a specification, not an implementation. There are multiple implementations of Go, and even a single implementation behaves differently on different processors. |
We did go through some effort to make sure pointer writes are atomic. Mostly to keep the garbage collector happy, but generally to prevent racy programs from going completely off the rails. See #13160. |
The memory model document, which is linked, is pretty explicit:
|
@ianlancetaylor, I hope the official docs can make it clear, for the offical gosdk, on which processor architectures and OSes, writes/reads scalar variable are atomic (or not), instead of a vague mention in a side article. @ianlancetaylor and could you provide an example on x64 linux to show writes/reads scalar variable aren't atomic? @randall77 thanks for the clarification, but only pointer writes are atomic? not for pointer reads? @adg but I can't find an example to support writes/reads scalar variable aren't atomic on x64 linux. |
You didn't answer my question about what precisely you mean by "atomic." It's not a simple question. For example, see http://en.cppreference.com/w/cpp/atomic/memory_order. That level of detail is appropriate for C++, but it is not something we aim for in Go. The Go guidelines try to be simple: use channels, use mutexes, use the sync/atomic package if you must.
No, I can't, because 1) you haven't defined your terms; 2) x86 processors always use a strict memory ordering model so there are many race conditions that can not be demonstrated on x86 but can be demonstrated on, for example, ARM and PPC processors. (Here is a pretty good paper on more relaxed memory models used on non-x86 processors: https://www.cl.cam.ac.uk/~pes20/ppc-supplemental/test7.pdf.) In short, you are asking for something that is simple and we are telling you that it is complicated. We are trying to make it simple by not answering your question, which would require many complex details, but instead addressing the overall issue at a higher level: use channels, use mutexes, use sync/atomic if you must. |
Pointer reads are currently atomic as well. As an example in the other direction, complex64 is not currently atomic on amd64. There are two different questions here that you're somewhat conflating. One is what current implementations do or do not provide atomicity for. The other is what atomicity guarantees the spec provides. The former is an interesting question about current implementations, but ultimately not very useful. The latter is what kind of guarantees we want to provide across all architectures and across all time. We don't want to commit to anything here, it may be too expensive to provide particular guarantees on some platforms. The ordering guarantees provided by locks & channels is all we want to commit to, and is all that is needed for 99% of programs. |
thanks all for the information! |
@randall77 can I ask what technology is used to make sure pointer writes/reads atomic? |
@yaxinlx As I think I keep saying, "atomic" doesn't mean just one thing. Keith is saying that the compiler generates the machine instructions that ensure that if two different processors write a pointer value to the same memory location simultaneously, other processors will see one value or the other value, but not a mixture. The "technology" is simply using whatever instructions the processor supports to make this happen. However, the compiler does not use instructions that guarantee anything about the visibility of those writes to other processors. It's quite possible, on some architectures, that if processors 1 and 2 write a pointer value simultaneously then processor 3 will see the value written by processor 1 and processor 4 will see the value written by processor 2. That said, please take further discussion of this off this issue and to a forum. See https://golang.org/wiki/Questions . Thanks. |
Uh oh!
There was an error while loading. Please reload this page.
go version
)?1.6
go env
)?Debian 8, Intel amd64 CPU.
I wrote a small program to test if reading/writing of scalar type variables is atomic.
expect panic if reading/writing of scalar type variables is not atomic
never panic.
The official golang documents don't mention whether or not reading/writing scalar type variables is atomic. There are some pieces of vague info in other pages, such as:
Many 3rd party articles and group posts say reading/writing scalar type variables is NOT atomic.
Are their statements correct for any processor architecture and OSes? or just for some ones?
I really hope golang official documents can make clear on this point.
The text was updated successfully, but these errors were encountered: