That post is fantastic and horrible at the same time. It is mandatory read for anyone endeavoring into concurrent programming however.
On Sun, Mar 18, 2018, 09:42 David Anderson <d...@natulte.net> wrote: > There's a difference though. The program that uses sync/atomic will behave > non-deterministically, but within a small set of possible outcomes. The one > without could do anything. In addition to producing an incorrect numeric > result, it could deadlock, segfault, jump execution to some random place in > the program code, ... > > I highly recommend > https://software.intel.com/en-us/blogs/2013/01/06/benign-data-races-what-could-possibly-go-wrong > . It's an excellent article (by the author of the go race detector) that > explains why safe, benign data races are never safe or benign. The examples > are in C++, but the same applies to Go - the compiler makes assumptions > about code execution in the absence of synchronization points, and even > simple optimizations can have hilarious consequences on code that violates > those assumptions. > > - Dave > > On Sun, Mar 18, 2018 at 1:19 AM, Devon H. O'Dell <devon.od...@gmail.com> > wrote: > >> Perhaps better illustrated: >> >> package main >> >> import ( >> "fmt" >> "time" >> ) >> >> type info struct { >> count int >> id int >> } >> >> var stop int32 >> >> func runner(id int, c chan info) { >> info := info{id: id} >> for stop == 0 { >> info.count++ >> time.Sleep(1 * time.Microsecond) >> } >> c <- info >> } >> >> func main() { >> c := make(chan info) >> for i := 0; i < 10; i++ { >> go runner(i, c) >> } >> >> time.Sleep(10 * time.Millisecond) >> stop = 1 >> >> for i := 0; i < 10; i++ { >> fmt.Printf("Returned %+v\n", <-c) >> } >> } >> >> This program is guaranteed to halt, regardless of any GOMAXPROCS >> setting. If you use the race detector on this program, it will >> complain. You can "fix" "the race" by changing the loop condition to >> "atomic.LoadInt32(&stop) == 0" and use atomic.StoreInt32(&stop, 1) as >> your signal. Is the program still racy? Yep. Is either version of this >> program buggy? That just depends. It's not too hard to think of cases >> where this behavior might be desirable; even lossy counters are a >> thing. >> >> --dho >> >> 2018-03-18 0:43 GMT-07:00 Devon H. O'Dell <devon.od...@gmail.com>: >> > 2018-03-16 2:16 GMT-07:00 Jérôme Champion <champ...@gmail.com>: >> >> Any race is a bug. When there is a race, the compiler is free to do >> whatever >> >> it wants. >> > >> > This is a false statement; whether or not a race constitutes a bug >> > depends on the encapsulating protocol. Consider the following: >> > >> > package main >> > >> > import ( >> > "fmt" >> > "sync" >> > "sync/atomic" >> > ) >> > >> > var wg sync.WaitGroup >> > >> > type Spinlock struct { >> > state uint32 >> > } >> > >> > func (s *Spinlock) Lock() { >> > for atomic.SwapUint32(&s.state, 1) == 1 { >> > } >> > } >> > >> > func (s *Spinlock) Unlock() { >> > atomic.StoreUint32(&s.state, 0) >> > } >> > >> > func locker(s *Spinlock, i int) { >> > defer wg.Done() >> > s.Lock() >> > fmt.Printf("Locker %d acquired lock\n", i) >> > s.Unlock() >> > } >> > >> > func main() { >> > s := &Spinlock{} >> > for i := 0; i < 10; i++ { >> > wg.Add(1) >> > go locker(s, i) >> > } >> > wg.Wait() >> > } >> > >> > This program does not have deterministic output because each goroutine >> > races to acquire the lock, and which gets it first relies on >> > scheduling, which is effectively stoachastic. (Playground caches >> > output, so no use illustrating it there.) Despite this, the program >> > compiles just fine and behaves correctly for any reasonable definition >> > of correct. >> > >> > I recognize this is not the issue mentioned in OP, but hopefully it's >> > clear that this is not just a semantics argument (race doesn't just >> > mean "only things the race detector can find") and that the statement >> > "any race is a bug" is false. This race only constitutes a bug when >> > the requirements of this program require deterministic output. >> > >> > --dho >> > >> >> What do you want to do? Do you want to println before or after >> >> cancelContext? In your example, println could even be executed during >> >> cancelContext! >> >> Your example is not enough, such program : >> >> https://play.golang.org/p/KJsYwu-ivjb would fix your problem, but I >> don't >> >> think that's what you asked for :) >> >> >> >> >> >> Le vendredi 16 mars 2018 03:11:49 UTC+1, Anmol Sethi a écrit : >> >>> >> >>> https://play.golang.org/p/82Um1jSntBo >> >>> >> >>> Please run with the race detector to see the race. >> >>> >> >>> This race condition arises because private variables are read via >> >>> reflection by the fmt package. Is there any elegant way to avoid such >> a >> >>> race? >> >>> >> >>> -- >> >>> Best, >> >>> Anmol >> >>> >> >> -- >> >> 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+unsubscr...@googlegroups.com. >> >> For more options, visit 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 golang-nuts+unsubscr...@googlegroups.com. >> For more options, visit 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 golang-nuts+unsubscr...@googlegroups.com. > For more options, visit 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 golang-nuts+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.