What Is Causing This Race Condition

I am taking a course on Udemy and as an exercise to demonstrate race conditions, we used the runtime.Gosched() method. However, when I comment the runtime.Gosched() line out (as show below), and run go run -race fileName.go I still get a race condition. I was advised by the instructor to come here and pose the question. Hoping someone can shed some light - def still a Go noob. :sweat_smile:

Thanks.

func simulateRaceCondition() {
	/******
	* Ex 3: Using goroutines, create an incrementer program
	* read the incrementer value, store it in a new variable, yield the processor with runtime.Gosched(), increment the new variable
	* show that a race condition is raised
	******/

	counter := 0
	goRoutines := 50
	var wg sync.WaitGroup
	wg.Add(goRoutines)

	for ; goRoutines != 0; goRoutines-- {
		go func() {
			temp := counter
			// runtime.Gosched()
			temp++
			counter = temp
			fmt.Println("counter", counter)
			wg.Done()
		}()
	}
	wg.Wait()
	fmt.Println(counter)
	fmt.Println("Done")
	fmt.Println(runtime.NumGoroutine())
}

1 Like

Hi, Branden,

Calling runtime.Gosched() suspends the current goroutine to allow another to run. If your code has a race condition, you’ll encounter it with or without that function call*. A race condition is when you have two or more concurrent accesses to a variable and at least one is a write. Your race condition is in how you concurrently change your counter variable from multiple goroutines without any synchronization.

* Assuming GOMAXPROCS is greater than 1 and you have more than 1 hardware threads on your computer. I think. I have an OK understanding of the x86 memory model, but not specifically Go’s.

4 Likes

Hey Sean,

Thanks for the detailed answer. I guess my question is based on the provided code, what could be causing this (just assume this was the entire application)? I was of the understanding that if I used WaitGroups properly, this should avoid the race condition scenario; is this incorrect? I will note that the final counter value is correct, however, so it doesn’t appear to be causing functionality issues, but the fact it’s triggering a race condition is troublesome to me.

The WaitGroup just makes sure that all the goroutines finish before execution continues after your call to Done. It doesn’t do anything else to make sure memory accesses are synchronized.

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.