Race Condition:
Race condition occurs, when 2 or more threads try to access the shared data of same program and try to change it. In java, the shared data may be the instance variables because for method variables, each thread has it's own copy.
Example:
package thread;
/**
* @author Sivaranjani D
*
*/
public class MultiThreadsDanger {
public static void main(String[] args) {
Runnable atm = new ATM();
Thread withdrwer1 = new Thread(atm);
withdrwer1.setName("withdrawer1");
withdrwer1.start();
Thread withdrwer2 = new Thread(atm);
withdrwer2.setName("withdrawer2");
withdrwer2.start();
}
}
class Account {
int balance = 500;
public void debit(int amount) {
balance = balance - amount;
}
public void credit(int amount) {
balance = balance + amount;
}
public int getBalance() {
return balance;
}
}
class ATM implements Runnable {
Account account = new Account();
public void run() {
for (int i = 0; i < 5; i++) { if (account.getBalance() > 0) {
makeWithdrawal(100);
} else {
System.out.println("Not enough in amount for "
+ Thread.currentThread().getName() + " to withdraw ");
}
}
}
private void makeWithdrawal(int amt) {
if (account.getBalance() >= amt) {
System.out.println(Thread.currentThread().getName()
+ " cheked balance and the balance is :"
+ account.getBalance());
account.debit(amt);
System.out.println(Thread.currentThread().getName()
+ " completes the withdrawal and the balance: "
+ account.getBalance());
}
}
}
Output
withdrawer1 cheked balance and the balance is :500
withdrawer1 completes the withdrawal and the balance: 400
withdrawer2 cheked balance and the balance is :400
withdrawer2 completes the withdrawal and the balance: 300
withdrawer2 cheked balance and the balance is :300
withdrawer2 completes the withdrawal and the balance: 200
withdrawer2 cheked balance and the balance is :200
withdrawer2 completes the withdrawal and the balance: 100
withdrawer2 cheked balance and the balance is :100
withdrawer2 completes the withdrawal and the balance: 0
Not enough in amount for withdrawer2 to withdraw
Not enough in amount for withdrawer2 to withdraw
Not enough in amount for withdrawer2 to withdraw
Not enough in amount for withdrawer2 to withdraw
Not enough in amount for withdrawer2 to withdraw
Not enough in amount for withdrawer2 to withdraw
withdrawer1 cheked balance and the balance is :400
withdrawer1 completes the withdrawal and the balance: -100
Not enough in amount for withdrawer1 to withdraw
Not enough in amount for withdrawer1 to withdraw
Not enough in amount for withdrawer1 to withdraw
Not enough in amount for withdrawer1 to withdraw
Not enough in amount for withdrawer1 to withdraw
Not enough in amount for withdrawer1 to withdraw
Not enough in amount for withdrawer1 to withdraw
Not enough in amount for withdrawer1 to withdraw
Explanation:
- The file has an account class, which has some methods to credit, debit and get balance
- There is a ATM class which implements runnable. This ATM has the account and it's run method has the provision to call withdrawal method
- In the main class, we have created 2 threads by passing the same ATM object. So both the threads are considered as a 2 with-drawers . Both the threads now calls the run method of same ATM object and both the threads runs in the same run block.
- Even though we are doing the balance check in the above program, the output shows -100. How this is happening??
- The reason is, the atomic operations are not accessed by a single thread. In the above program atomic operation is, checking the balance and debit (inside withdrawal method). For example, consider the account has a balance of 100. And think now the first thread is doing the balance check. That means it executes the line if (account.getBalance() >= amt) . Now it succeeds in this line because we have 100 as balance and the amt to be debited is also 100. So next it will call the account.debit(amt); But as we know thread scheduler may stop this thread before executing the debit step and save it's state. Now, the second thread comes and it does the same first step. This also succeeds, because still the first thread has not debited. so the second thread also calls the second statement. It debits the amount and balance will becomes zero. Since the second thread finished its job it will die. Now the thread scheduler may again resumes the first thread, which was stopped after balance check. So now the first thread starts from where it paused. That means it start with the debit. So now we will get the -100 as output.
This situation is called as race condition.
No comments:
Post a Comment