As in the title, are read and write operations regarding uint8, atomic? Logically it must be a single cpu instruction obviously to read and write for a 8 bit variable. But in any case, two cores could simultaneously read and write from the memory, is it possible to create a stale data this way?
-
1obligatory: https://software.intel.com/en-us/blogs/2013/01/06/benign-data-races-what-could-possibly-go-wrong – JimB Mar 21 '16 at 14:36
-
Does the OP worry that 8 bits might not be sent to or from RAM or a cache line or a core register coherently? Or that data, once read, could be stale because of another core's write? The last sentence asks about stale data, and yes, data can become stale in one core, or in one goroutine, if another goroutine has logic to write to that 8 bit location. Gophers prefer to use coroutines and channels. If you haven't seen the recommendation "Do not communicate by sharing memory; instead, share memory by communicating", please see https://blog.golang.org/share-memory-by-communicating. – WeakPointer Mar 21 '16 at 16:55
-
@WeakPointer I saw it. I have read all the documentation. In my case, I am required to use locks, however I preferred to avoid it by atomic variables for cleaner code. So, this said 8 bit data, could it be stale even if there was 1 core? – Ozum Safa Mar 21 '16 at 19:39
-
2@OzumSafa: it depends on what you mean by "stale". If you want visibility between goroutines, there's no guarantees unless you create a ["happens before"](https://golang.org/ref/mem#tmp_2) relationship between writing and reading the value. Atomic operations guarantee that the value is read and written in its entirety into memory, but only locks and channels can create a "happens before" ordering to ensure the reads and writes between goroutines are synchronized. – JimB Mar 22 '16 at 13:33
2 Answers
No. If you want atomic operations, you can use the sync/atomic
package.
If you mean "would 8bit operations be atomic even if I ignore the Go memory model?", then the answer is still, it depends probably not.
If the hardware guarantees atomicity of read/write operations, then it might be atomic. But that still doesn't guarantee cache coherence, or compiler optimizations from reordering operations. You need to serialize the operations somehow, with the primitives Go provides in the "atomic" package, and using the "sync" package and channels to coordinate between goroutines.

- 104,193
- 13
- 262
- 255
There's no guarantee that the access on native types are on any platform atomic. This is why there is sync/atomic
. See also the advice in the memory model documentation.
Example for generic way of atomically setting a value (Play)
var ax atomic.Value // may be globally accessible
x := uint8(5)
// set atomically
ax.Store(x)
x = ax.Load().(uint8)
Probably more efficient solution for uint8
(Play):
var ax int64 // may be globally accessible
x := uint8(5)
atomic.StoreInt64(&ax, 10)
x = uint8(atomic.LoadInt64(&ax))
fmt.Printf("%T %v\n", x, x)

- 55,207
- 13
- 135
- 135
-
1Oh sweet, I was clever :). Thanks for the answer I did not realize I could use atomic.Value, and predefined methods did not work for me. – Ozum Safa Mar 21 '16 at 14:55
-
Although, do you know if this atomic.Value is simply a lock system underneath? Because being able to make any data type atomic does not seem possible in cpu level :) – Ozum Safa Mar 21 '16 at 14:56
-
1@OzumSafa: You can load and store anything "atomically"(indirectly) by using a pointer. `atomic.Value` is a little more complex in that it uses the 2 words for the `interface{}`, but it's the same concept. – JimB Mar 21 '16 at 15:00
-