A question about the atomic operations in golang

761 views
Skip to first unread message

陈诚

unread,
Jan 8, 2017, 1:17:56 PM1/8/17
to golang-nuts
Is the size of a pointer value 32 bits or 64 bits in golang when build with `GOARCH=amd64` option specified and running on 64-bit OS?
If it's 64-bit size, is a global pointer value 8-byte aligned in memory so that a read or write operation of that pointer value is carried out atomically?
For example, in the following code, is it possible that the global pointer p is only partially updated when the read goroutine read the pointer?
var p *int

void main() {
    i := 1
    p = &i
    go func() { fmt.Println(*p) } ()
}

The scenario I'm concerning is that there is only one write but multiple reads on a global pointer value, and reading of an old value of the pointer is not important. Thanks in advance!

Dave Cheney

unread,
Jan 8, 2017, 2:17:37 PM1/8/17
to golang-nuts
What you are talking about is called a torn write, which can occur if a value is written to memory but not aligned properly as the processor or memory subsystem must convert this write into two to correct for the miss alignment.

Most processors that I know of, and all the ones that Go supports, assuming that the value is correctly alligned will write the value atomically, IE another processor will not see a partially written value.

However, I must caution you that while you say it is ok for one processor to see an old value for a time, this is not how the Go memory model works. There are no concessions for "for a time" and so on, the updated value may never be written to memory, or the old value may continue to be visible for the remainder of the program's run time.

The memory model describes what you ask for as a data race and states that your program is no longer guaranteed to run correctly. Or put more suscinctly, if you have a data race, the result of your program is undefined.

Caleb Doxsey

unread,
Jan 8, 2017, 5:22:12 PM1/8/17
to golang-nuts
Shouldn't this particular case be ok? From the memory doc: https://golang.org/ref/mem

The go statement that starts a new goroutine happens before the goroutine's execution begins.

So the write has to happen before the goroutine starts. At least that's what the example indicates:
 
For example, in this program: 
 
var a string
func f() {
print(a)
}
func hello() {
a = "hello, world"
go f()
}
 
calling hello will print "hello, world" at some point in the future (perhaps after hello has returned).

Konstantin Khomoutov

unread,
Jan 9, 2017, 5:30:59 AM1/9/17
to 陈诚, golang-nuts
On Sun, 8 Jan 2017 01:22:59 -0800 (PST)
陈诚 <ncu....@gmail.com> wrote:

> Is the size of a pointer value 32 bits or 64 bits in golang when
> build with `GOARCH=amd64` option specified and running on 64-bit OS?
[...]

Isn't it http://stackoverflow.com/q/41531337/720999 ?

陈诚

unread,
Jan 9, 2017, 8:39:31 AM1/9/17
to golang-nuts, ncu....@gmail.com
Yes, the author of that post is also me : )

在 2017年1月9日星期一 UTC+8下午6:30:59,Konstantin Khomoutov写道:

陈诚

unread,
Jan 9, 2017, 8:46:13 AM1/9/17
to golang-nuts
Yes, I think you are right about the case in my sample code. The code doesn't show exactly what I'm concerned about. I just wanna know whether a write to a global pointer in 64-bit machine an atomic operation or not.

在 2017年1月9日星期一 UTC+8上午6:22:12,Caleb Doxsey写道:

Axel Wagner

unread,
Jan 9, 2017, 8:59:08 AM1/9/17
to 陈诚, golang-nuts
The answer (like with virtually all questions like this on golang-nuts) is: Possibly, but you can not rely on it. Assuming that it is might break your program now or at a non-specific future date or on a non-specific current or future processor.

If you need atomic operations, please use the sync/atomic package. If you don't, your program is incorrect and go tooling will complain about it being incorrect.

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

陈诚

unread,
Jan 9, 2017, 9:03:25 AM1/9/17
to golang-nuts
Thanks for your caution. Then is there a way to know that a certain variable is aligned properly? Will the compiler make the global variable `var p *int` in my sample code aligned properly?

在 2017年1月9日星期一 UTC+8上午3:17:37,Dave Cheney写道:

Axel Wagner

unread,
Jan 9, 2017, 9:15:25 AM1/9/17
to 陈诚, golang-nuts
The only guarantees made in regards to alignment are the ones outlined here:
From what I can tell, there is no such guarantee. But why do you care, specifically? Using the sync/atomic package will handle this correctly in every case. This reeks of an XY-problem - what is the actual problem you are trying to solve? There likely is a better way to handle your problem (e.g. you say that there is only a single write, so sync.Once might help? Or sync.Cond?). When I said your program will be incorrect, I wasn't being cautious, I was being literal.

--

Dave Cheney

unread,
Jan 9, 2017, 4:54:47 PM1/9/17
to golang-nuts
Unless you're using a 64bit atomic on a 32 bit platform, there is nothing to worry about.
Reply all
Reply to author
Forward
0 new messages