Track down race conditions with Go

If program parts running in parallel keep interfering with each other, you may have a race condition. Mike Schilli shows how to instruct the Go compiler to detect these conditions and how to avoid them in the first place.

If programmers are not careful, program parts that are running in parallel will constantly get in each other’s way, whether as processes, threads, or goroutines. If you leave the order in which system components read or modify data to chance, you are adding time bombs to your code. They will blow up sooner or later, leaving you with runtime errors that are difficult to troubleshoot. But how do you avoid them?

The common assumption that components will run in the same order that a program calls them is a fallacy – one easily refuted with an example such as in Listing 1. But coincidence can also be a factor. It is quite possible for something to work once but then crash after a small, and often unrelated, change to the code. The load on the system you are using can also play a role: Something may work flawlessly in slack times but fall apart unexpectedly under a heavy load.

The fact that unsynchronized goroutines do not run in the order in which they are defined, even if the program starts them one after the other, is nicely illustrated by Listing 1 [1] and the output in the upper part of Figure 1. Although the for loop starts goroutine   first, followed by 1, then 2, and so on, as defined by the index numbers in i, the upper part of Figure 1 makes it clear from the compiled program’s output that chaos reigns, and the goroutines write their messages to the output as a wildly confusing mess.


Use Express-Checkout link below to read the full article (PDF).

Posted by Contributor