It is not the writing - it is the reading, and what is “visible”.

The point was that you need to use atomics if you write to ANY structure field 
and read that field from another Go routine - barring any other synchronization 
method (WaitGroup, Lock, etc.)

The secondary point is, if you use atomics, then there can be a performance hit 
due to false sharing, which is why I stated you can use gaps between this 
elements (in the example, use a larger array and put the counters at one every 
N elements) to avoid this. False sharing is typically understood to be 
referencing the performance issue - not a correctness issue.



> On Feb 1, 2019, at 12:20 PM, roger peppe <[email protected]> wrote:
> 
> 
> 
> On Fri, 1 Feb 2019, 4:11 pm robert engels <[email protected] 
> <mailto:[email protected]> wrote:
> There is nothing reading the value in that code - so that would always be 
> safe…
> 
> Here is a more common example that many people get wrong (pseudo code)
> 
> struct {
>    a int
> }
> 
> go routine #1:
> 
> for {
>    A.a = A.a + 1
> }
> 
> go routine #2 :
> 
> for {
>    if A.a > 100 {
>       break
> }
> 
> 
> Go routine #2 may never see the value of A.a change and so never exit the 
> loop.
> 
> Indeed, though the topic here was specifically about writing to different 
> fields of the same struct.
> 
> 
> 
> 
>> On Feb 1, 2019, at 9:43 AM, roger peppe <[email protected] 
>> <mailto:[email protected]>> wrote:
>> 
>>  On Fri, 1 Feb 2019, 3:18 pm Robert Engels <[email protected] 
>> <mailto:[email protected]> wrote:
>> To clarify though, you still need to use atomics. 
>> 
>> Really? For writing to different fields in a struct? So the following code 
>> is not generally safe?
>> (I often rely on this kind of code being safe so if it isn't, I need to 
>> know!).
>> 
>> type S struct {
>>    a A
>>    b B
>> }
>> 
>> func (s *S) W() {
>>     var wg sync.WaitGroup
>>     wg.Add(2)
>>     go func() {
>>        var a A
>>        s.a = a
>>        wg.Done()
>>     }()
>>     go func() {
>>        var b B
>>        s.b = b
>>        wg.Done()
>>     }()
>>     wg.Wait()
>> }
>> 
>> 
>> On Feb 1, 2019, at 8:52 AM, roger peppe <[email protected] 
>> <mailto:[email protected]>> wrote:
>> 
>>> 
>>> 
>>> On Thu, 3 Aug 2017, 8:45 am Dave Cheney <[email protected] 
>>> <mailto:[email protected]> wrote:
>>> 
>>> 
>>> On Thu, 3 Aug 2017, 17:39 Dave Cheney <[email protected] 
>>> <mailto:[email protected]>> wrote:
>>> Your first program has a data race, well it has two races, the first is a 
>>> data race between the goroutines writing to the slice and the println which 
>>> will read the contents of the slice. That is, if those writing goroutines 
>>> get a chance to run before main exits. 
>>> 
>>> The second program doesn't have a data race as the waitgroup.done / wait 
>>> creates a happens before relationship between reader and writer. 
>>> 
>>> 
>>> On Thu, 3 Aug 2017, 17:33 Henrik Johansson <[email protected] 
>>> <mailto:[email protected]>> wrote:
>>> But isn't this what is happening in the example? Or is write-only not 
>>> sharing? 
>>> 
>>> 
>>> On Thu, 3 Aug 2017, 09:23 Dave Cheney, <[email protected] 
>>> <mailto:[email protected]>> wrote:
>>> IMO you need a lock whenever you are sharing a value between goroutines by 
>>> storing it in memory.
>>> 
>>> 
>>> On Thu, 3 Aug 2017, 17:21 Henrik Johansson <[email protected] 
>>> <mailto:[email protected]>> wrote:
>>> I think I am mostly after a mental pattern to easily recognise when 
>>> synchronizations are needed.
>>> 
>>> I am decently good at this but I tend to be very conservative and use locks 
>>> and atomics perhaps when they are not needed.
>>> But here we have several goroutines all taking part in the initialisation 
>>> itself concurrently writing to the same array. How can this be safe in 
>>> light of https://golang.org/ref/mem#tmp_10 
>>> <https://golang.org/ref/mem#tmp_10> . I get that your comment about 
>>> "happens before" comes in here if there were any readers but eventually 
>>> there will be readers or we would never need to do this. If the main after 
>>> some time wants to access these values is it enough to make sure the 
>>> goroutines are done perhaps using a WaitGroup or do we have to use some 
>>> other synchronisation to ensure the visibility of the data in the array?
>>> 
>>>  https://play.golang.org/p/8BfrPhyIEb <https://play.golang.org/p/8BfrPhyIEb>
>>> 
>>> Or is it needed to do something like this:
>>> 
>>> https://play.golang.org/p/9QgTP5Dqc7 <https://play.golang.org/p/9QgTP5Dqc7>
>>> 
>>> I mean aside from the poor form of sleeping like this, the idea is to 
>>> simulate usage "at some point later in time".
>>> 
>>> It gets hypothetical pretty quick and usually when this happens I make sure 
>>> to create a new array/slice/whatever and then atomically swap it before 
>>> some other goroutine uses it but I generally avoid indexing assignment from 
>>> go routines like this even though it seems to be ok.
>>> 
>>> Does this hold for slices as well as for arrays?
>>> 
>>> Yes, it is safe for multiple goroutines to write to different array 
>>> elements, the same is true for slices as they are backed by an array
>>> 
>>> What about assignments to fields in structs?
>>> 
>>> Yes.
>>> 
>>> Can several goroutines safely write to different fields in the same struct 
>>> assuming they are word sized?
>>> 
>>> Yes, although they should also be naturally aligned. 
>>> 
>>> Can you explain your reasoning here a little more, please? As far as I am 
>>> aware it is always ok to write concurrently to different fields in the same 
>>> struct and if that's not the case then I have some serious code review to 
>>> do!
>>> 
>>> 
>>> Does this hold for all architectures?
>>> 
>>> Some architectures have issues with atomic writes to values smaller than a 
>>> word. Look for xor8 in the runtime source.
>>> 
>>> Writing to adjacent memory locations will cause false sharing between CPU 
>>> caches. This is a performance, not a correctness issue. 
>>> 
>>> 
>>> I am sorry if I am still a bit unclear but I find it hard to ask properly 
>>> when I am a bit unsure of the topic. :D
>>> 
>>> 
>>> 
>>> tors 3 aug. 2017 kl 07:49 skrev Dave Cheney <[email protected] 
>>> <mailto:[email protected]>>:
>>> I'm not really sure what you are asking. I think your second paragraph got 
>>> eaten by autocorrect at the critical point. Could try maybe asking your 
>>> question in a different way?
>>> 
>>> 
>>> --
>>> 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 [email protected] 
>>> <mailto:golang-nuts%[email protected]>.
>>> For more options, visit https://groups.google.com/d/optout 
>>> <https://groups.google.com/d/optout>.
>>> 
>>> -- 
>>> 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 [email protected] 
>>> <mailto:[email protected]>.
>>> For more options, visit https://groups.google.com/d/optout 
>>> <https://groups.google.com/d/optout>.
>>> 
>>> -- 
>>> 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 [email protected] 
>>> <mailto:[email protected]>.
>>> For more options, visit https://groups.google.com/d/optout 
>>> <https://groups.google.com/d/optout>.
>> 
>> 
>> -- 
>> 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 [email protected] 
>> <mailto:[email protected]>.
>> For more options, visit https://groups.google.com/d/optout 
>> <https://groups.google.com/d/optout>.
> 
> 
> -- 
> 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 [email protected] 
> <mailto:[email protected]>.
> For more options, visit https://groups.google.com/d/optout 
> <https://groups.google.com/d/optout>.

-- 
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 [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to