- Can this test ever fail on x86, x64, ARM?
If so, is it possible to make it fail (in some sort of setup) and without changing the test code itself?
func Test_WaitGroup_Simple(t *testing.T) { var condition bool var wg sync.WaitGroup wg.Add(1) go func() { condition = true wg.Done() }() wg.Wait() if !condition { t.Error("Condition is false. But expected was true.") } }

- 3,601
- 2
- 23
- 32

- 2,270
- 3
- 31
- 36
-
3it will never enter the condition. – Aug 27 '17 at 17:50
2 Answers
I have changed abit your test to make comparsion between atomic module:
package main
import (
"sync"
// "sync/atomic"
"fmt"
)
func main() {
var condition int32
var wg sync.WaitGroup
wg.Add(1)
go func() {
condition = 101
//atomic.StoreInt32(&condition,101)
wg.Done()
}()
wg.Wait()
if condition != 101 {
fmt.Println("Condition is false. But expected was true.")
} else {
fmt.Println("Ok.")
}
}
https://play.golang.org/p/8ewy2uMNNH
With go asm we can check what code will be produced
go tool compile -S t.go
Here is production of inline code from
atomic.StoreInt32(&condition,101)
0x001d 00029 (t.go:15) MOVL $101, AX
0x0022 00034 (t.go:15) MOVQ "".&condition+24(FP), CX
0x0027 00039 (t.go:15) XCHGL AX, (CX)
0x0029 00041 (t.go:16) MOVQ "".&wg+32(FP), AX
0x002e 00046 (t.go:16) MOVQ AX, (SP)
0x0032 00050 (t.go:16) PCDATA $0, $1
0x0032 00050 (t.go:16) CALL sync.(*WaitGroup).Done(SB)
Here is production of
condition = 101
0x001d 00029 (t.go:14) MOVQ "".&condition+24(FP), AX
0x0022 00034 (t.go:14) MOVL $101, (AX)
0x0028 00040 (t.go:16) MOVQ "".&wg+32(FP), AX
0x002d 00045 (t.go:16) MOVQ AX, (SP)
0x0031 00049 (t.go:16) PCDATA $0, $1
0x0031 00049 (t.go:16) CALL sync.(*WaitGroup).Done(SB)
As You see there is not so much difference on the code. I have used int32 just to make the clean the difference for both cases. but go produces , more or less the same code for other atomic types including bool
If You look at the implementation of atomic/store function on i386 platform it acttually do nothing:
sync/atomic/asm_amd64.s
TEXT ·StoreUint32(SB),NOSPLIT,$0-8
MOVL addr+0(FP), BP
MOVL val+4(FP), AX
XCHGL AX, 0(BP)
RET
But store 64 bit on 32 platform is already tricky and of course can not be replaced with simple "=" operation.
Thats why my answer is: This test will always pass on atleast 386 and amd64 platforms. The other thing that it is a bad practice - but it is actually the story from the other ticket.

- 3,080
- 3
- 40
- 51
-
thanks for the hard work on this in the first place! But you are comparing version with atomic to without. As far as I know, atomic does not guarantee visibility in the other goroutine. So if you are trying to prove the point that there is no difference between the two therefore it must be safe, that argument is not working. If this test can never fail it's presumably in the (accidental or undocumented) properties of Wait call. – honzajde Aug 28 '17 at 13:23
-
do You mean that this case : https://play.golang.org/p/3MCpNJ7YKd , can also fail (if we assume that Your test can fail )? – Oleg Aug 28 '17 at 13:37
-
Now Actually I have got your question. It would be nice to know that this case can fail. By the way Wait just tests inner state variable and if needed do goyield. – Oleg Aug 28 '17 at 13:59
-
Actually, I did some more research on the topic. And it's complicated: official go spec does not say anything about atomic. But there is something they call 'litmus tests' and it tests that atomic operations are actually useful and yes the visibility is there! For sure atomic prevents data race. It's visibility guarantees are given by those litmus tests. Have to find out more about them (which platforms, etc...) It's covered here: https://github.com/golang/go/issues/5045 – honzajde Aug 28 '17 at 14:13
-
and if you add atomic and remove wait group from this example it is still incorrect, that is more then clear... – honzajde Aug 28 '17 at 14:16
-
I remember somebody having issue with atomic and visibility in go, but I can not find the article or which platform it was, but that was some time ago... – honzajde Aug 28 '17 at 14:24
-
but that can be only optimized compilation for this example, possible? – honzajde Aug 28 '17 at 14:33
-
I dont think so , but what should / could be called to release memory barrier ? – Oleg Aug 28 '17 at 15:01
-
Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/153044/discussion-between-oleg-golovanov-and-honzajde). – Oleg Aug 28 '17 at 15:16
It can't. See Does WaitGroup.Wait() imply memory barrier in this case?. Thanks a lot to @OlegGolovanov for looking at go's ASM.

- 2,270
- 3
- 31
- 36