I know it can happen that g prints 2 and then 0 given the following code.
var a, b uint32
func f() {
a = 1
b = 2
}
func g() {
fmt.Println(b)
fmt.Println(a)
}
func main() {
go f()
g()
}
What if I change all read and write to atomic operations? Is that guaranteed that if g prints 2 first, then 1 is also printed?
var a, b uint32
func f() {
atomic.StoreUint32(&a, 1)
atomic.StoreUint32(&b, 2)
}
func g() {
fmt.Println(atomic.LoadUint32(&b))
fmt.Println(atomic.LoadUint32(&a))
}
func main() {
go f()
g()
}
There are two ways to accomplish an atomic operation: Use a single machine instruction. Tell the operating system in advance not to interrupt the operation.
In simple words, the atomic means the operation will be either completed or not. The other threads or CPUs won't catch it in the middle of the operation.
Atomic operations are important in programs where a shared resource, such as a database, is accessed by multiple threads. An atomic operation is an operation that appears to be instantaneous in the eyes of the other threads. In other words, you cannot catch an atomic operation in the middle.
An atomic access is a term for a series of accesses to a memory region. Atomic accesses are used by managers when they would like to perform a sequence of accesses to a particular memory region, while being sure that the original data in the region are not corrupted by writes from other managers.
Practically it will work as you described. The Go compiler won't re-order atomic operations and atomic store is implemented using XCHG on amd64 (and similar instructions on other architectures): https://github.com/golang/go/blob/release-branch.go1.8/src/cmd/compile/internal/ssa/gen/AMD64.rules#L472
This behaviour is not specified at the moment (as of Go 1.8) and might change, see discussion at https://github.com/golang/go/issues/5045 for more insights.
No. There's no synchronization, so there is no "happens before" relationship.
Synchronization between goroutines is done via channel communication and lock operations.
A key paragraph in the memory model is:
Within a single goroutine, reads and writes must behave as if they executed in the order specified by the program. That is, compilers and processors may reorder the reads and writes executed within a single goroutine only when the reordering does not change the behavior within that goroutine as defined by the language specification. Because of this reordering, the execution order observed by one goroutine may differ from the order perceived by another. For example, if one goroutine executes a = 1; b = 2;, another might observe the updated value of b before the updated value of a.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With