As per Wikipedia, race condition is defined as the condition of an electronics, software, or other systems where the system's substantive behavior is dependent on the sequence or timing of other uncontrollable events. Race condition falls under the "Concurrency" department. Concurrency is the art of making progress on multiple tasks simultaneously. Let's understand what concurrency actually means.
Consider the following scenario to understand concurrency in a better way. Imagine a basket full of laddoos and two people standing near the basket. One is assigned a task to measure the count, quality, weight, and examine other important features of each and every laddu in the basket. Now as soon as he begins to observe the laddoos to derive some conclusion, simultaneously the second person tampers some laddoos shape, beats them so they're powdered, and even eats some bits of some laddoos. It's happening simultaneously: one taking note of the features of laddoos & the other damaging the original features. Now there's no way in the world that the first one knows the original data as he's only taking note of the tampered data which even he is unaware of. This is a
race condition. Both tasks executing simultaneously interfering with some common things leading to a great deal of data loss.
Lets code and understand race condition practically!
go
package main
import (
"fmt"
"time"
)
func execute(some string) {
// initializing a infinite for loop
for i := 1; true; i++ {
// prints string and number
fmt.Println(some, i)
// this makes the program sleep for
// 100 milliseconds, wiz 10 seconds
time.Sleep(time.Millisecond * 100)
}
}
func main() {
// Simple go synchronous program
// without any concurrency
execute("First")
// when this func is called it executes
// and then passes on to next line
execute("Second")
// after the first second is to be executed
// the problem is, execute function will
// never finish execution, its trapped
// in an infinite loop so the program will
// never move to second execution.
fmt.Println("program ends successfully")
// if I'm wrong and both first and second
// execute, then this line should print too
// check the output
}

If you use Windows, you're likely to see such output on the screen. The above output goes on like that and has no end unless you manually stop it or it runs out of system memory for execution.
Consider the second code.
go
package main
import (
"fmt"
"time"
)
func execute(some string) {
// initializing a infinite for loop
for i := 1; true; i++ {
// prints string and number
fmt.Println(some, i)
// this makes the program sleep for
// 100 milliseconds, wiz 10 seconds
time.Sleep(time.Millisecond * 100)
}
}
func main() {
// Simple go program with concurrency
go execute("First")
// Placing the go command infront of the
// func call simply creates a goroutine
execute("Second")
// The goroutine ensures that both functions
// execute simultaneously & successfully
fmt.Println("program ends successfully")
// This statement still won't execute because
// the func call is stuck in an infinite loop
// check the output
}

If you use Windows, you're likely to see such output on the screen. When you create a
goroutine in Go, it typically makes the execution faster by giving off the waiting time to other prevailing tasks, Now let's see what happens if you create two goroutines in the same program.
go
package main
import (
"fmt"
"time"
)
func execute(some string) {
// initializing a infinite for loop
for i := 1; true; i++ {
// prints string and number
fmt.Println(some, i)
// this makes the program sleep for
// 100 milliseconds, wiz 10 seconds
time.Sleep(time.Millisecond * 100)
}
}
func main() {
// Simple go program with concurrency
go execute("First")
// Placing the go command in front of the
// func call simply creates a goroutine
go execute("Second")
// The second goroutine, you may think that the
// program will now run with lightning speed
// But, both goroutines go to the background
// and result in no output at all Because the
// program exits after the main goroutine
fmt.Println("Program ends successfully")
// This statement will now be executed
// and nothing else will be executed
// check the output
}

If you use Windows, you're likely to see such output on the screen. Let's consider one race condition scenario to wind up our topic:
go
package main
// one goroutine is the main
// goroutine that comes by default
import (
"fmt"
"runtime"
"sync"
)
var wgIns sync.WaitGroup
func main() {
// shared variable
counter := 0
// the other 10 goroutines are
// supposed to come from here
wgIns.Add(10)
for i := 0; i < 10; i++ {
// goroutines are made
go func() {
for j := 0; j < 10; j++ {
// shared variable execution
counter += 1
// 100 should be the counter value but
// it may be equal to 100 or lesser
// due to race condition
}
wgIns.Done()
}()
}
// this value should actually be 11
fmt.Println("The number of goroutines before wait = ", runtime.NumGoroutine())
wgIns.Wait()
// value should be 100
fmt.Println("Counter value = ", counter)
fmt.Println("The number of goroutines after wait = ", runtime.NumGoroutine())
// this value is supposed to be 1
// but lets see if these values
// stay consistently same every
// time we run the code
}

This inconsistency happens because of race conditions. Race condition in simple terms can be explained as, you have one candy and two kids run to you claiming that they're both hungry. They both end up fighting for that one chocolate, they race to get the candy. This is a race condition. Here the solution is: get another candy so that the two enjoy a candy peacefully. Likewise, we can increase the resources allocation in order to ensure race condition does not occur.
Similar Reads
Time Durations in Golang
Operations related to time and date are a crucial part of software development (example log keeping). Go standard library provides a time package that has many functions and methods to deal with date and time. The operating system measures two types of time "Wall clock" time and "Monotonic" time. Wa
3 min read
bits Package in Golang
Go language provides inbuilt support for bit counting and manipulation functions for the predeclared unsigned integer types with the help of the bits package. .bits-package-Golang-table { border-collapse: collapse; width: 100%; } .bits-package-Golang-table td { border: 1px solid #5fb962; text-align:
6 min read
Connection with Postgres in Golang
PostgreSQL is the most widely used free and open-source relational database. Its greatest value lies in its robustness, scalability, and commitment to SQL standards. In this article, we will see how to connect to a PostgreSQL database using the Go programming language. Go's packages, plus libraries
2 min read
Combining Conditional Statements in Golang
Go is a open-source programming language developed at Google by Robert Griesemer, Rob Pike, and Ken Thompson. Go is similar to C syntactically but with CSP style concurrency and many features of other robust programming language. Often refereed to as Golang because of the domain name, this language
2 min read
fmt Package in GoLang
Prerequisite: Packages in GoLang and Import in GoLang Technically defining, a package is essentially a container of source code for some specific purpose. Packages are very essential as in all programs ranging from the most basic programs to high-level complex codes, these are used. A package ensur
13 min read
Atomic Variable in Golang
In Go language, Atomic Variables are utilized in order to control state. Here, the "sync/atomic" package must be used to use these variables. Moreover, it also prevents race conditions which allows two or more Goroutines to access identical sources. The Atomic counters are available for several goro
3 min read
Time Formatting in Golang
Golang supports time formatting and parsing via pattern-based layouts. To format time, we use the Format() method which formats a time.Time object. Syntax: func (t Time) Format(layout string) string We can either provide custom format or predefined date and timestamp format constants are also availa
2 min read
Type Assertions in Golang
Type assertions in Golang provide access to the exact type of variable of an interface. If already the data type is present in the interface, then it will retrieve the actual data type value held by the interface. A type assertion takes an interface value and extracts from it a value of the specifie
2 min read
main and init function in Golang
The Go language reserve two functions for special purpose and the functions are main() and init() function.main() functionIn Go language, the main package is a special package which is used with the programs that are executable and this package contains main() function. The main() function is a spec
2 min read
filepath Package in Golang
Go language provides inbuilt support for implementing utility routines for manipulating filename paths in a way compatible with the target operating system-defined file paths with the help of the filepath package. This package uses either forward slashes or backslashes (depending on the operating sy
3 min read