Drathier
Drathier

Reputation: 14539

Is variable assignment atomic in go?

If I have two threads concurrently modifying a string field on a struct, will I always see one or the other string assigned to the field, but nothing else?

Upvotes: 15

Views: 8736

Answers (2)

Quân Anh Mai
Quân Anh Mai

Reputation: 630

As of today, the version on June 6, 2022 of the Go memory model guarantees that a memory access not larger than a machine word is atomic.

Otherwise, a read r of a memory location x that is not larger than a machine word must observe some write w such that r does not happen before w and there is no write w' such that w happens before w' and w' happens before r. That is, each read must observe a value written by a preceding or concurrent write.

However, a string is definitely larger than a machine word, so your accesses are not guaranteed to be atomic. In this case, the result is unspecified, but it is most likely to be an interleave of different parts from different writes.

Reads of memory locations larger than a single machine word are encouraged but not required to meet the same semantics as word-sized memory locations, observing a single allowed write w. For performance reasons, implementations may instead treat larger operations as a set of individual machine-word-sized operations in an unspecified order. This means that races on multiword data structures can lead to inconsistent values not corresponding to a single write. When the values depend on the consistency of internal (pointer, length) or (pointer, type) pairs, as can be the case for interface values, maps, slices, and strings in most Go implementations, such races can in turn lead to arbitrary memory corruption.

Note that sync/atomic provides not only atomicity, but also sequential consistency. As a result, for accesses not larger than machine word, sync/atomic only provides additional sequential consistency.

The APIs in the sync/atomic package are collectively “atomic operations” that can be used to synchronize the execution of different goroutines. If the effect of an atomic operation A is observed by atomic operation B, then A is synchronized before B. All the atomic operations executed in a program behave as though executed in some sequentially consistent order.

The preceding definition has the same semantics as C++’s sequentially consistent atomics and Java’s volatile variables.

Upvotes: 7

Mr_Pink
Mr_Pink

Reputation: 109417

No. If you need atomic operations, there is sync/atomic.

The Go Memory Model will have all the related details. From the top of the Memory Model document:

Programs that modify data being simultaneously accessed by multiple goroutines must serialize such access.

To serialize access, protect the data with channel operations or other synchronization primitives such as those in the sync and sync/atomic packages.

Upvotes: 21

Related Questions