Race Condition
Introduction
One of the most common problems in multithreaded applications is the problem of race conditions.
In this tutorial, we’ll learn what race conditions are and how are they introduced into the system.
What is a Race Condition?
A race condition occurs when two or more threads have access to the same data and both try to update it simultaneously.
Let's take a block of code and try to understand what can go wrong with the below code and what the Race Condition is.
func Transfer(amount, accountA, accountB) {
if accountA.amount < amount {
return
}
accountB += amount
accountA -= amount
}
Synchronous Transactions
Let's assume we have 500 dollars in both accounts. And we are attempting to perform 2 different transactions one after the other.
In the first transaction, we transfer 200 dollars from Account A to Account B. In the second transaction, we try to transfer 400 dollars from Account A to Account B.
The above image shows how two transactions are performed one after the other. And this is something that we are expecting as well.
Asynchronous Transactions
As long as the transactions are happening synchronously, there will be no problem at all. But if both these transactions are carried out asynchronously. There will be a problem. Let's see how.
As you can see, when both these transactions are running asynchronously, the final results can be wrong and this situation is known as Race Condition.
How can we make sure that our program is Thread Safe?
There are two kinds of approaches to fighting race conditions:
- Avoiding Shared State
- Using Synchronizations and Atomic Operations
We will learn about them in the upcoming chapters.