I am new to thread programming in Java. To understand threading I’m trying to write a simple program to simulate a bank account. I just implemented withdrawal and trying to test it.
First few lines of the output is below.
Balance before T2 withdrawl: 1000
Balance after T2 withdrawl: 990
Balance before T1 withdrawl: 1000
Balance after T1 withdrawl: 980
Balance before T2 withdrawl: 980
Balance after T2 withdrawl: 970
Balance before T1 withdrawl: 970
Balance after T1 withdrawl: 960
My question is why the line 3 (Balance before T1 withdrawl: 1000) in the output gives 1000 instead of 990. If it was correct it should be on line 2. Am I missing some thing. Is my approach is correct?
My guess is that both threads trying to write to write to the console and thread T1 simply did not get a chance to write it on the second line.
class BankAccount {
private volatile int balance;
public BankAccount(int b){
balance = b;
}
public BankAccount(){
balance = 0;
}
synchronized public int getBalance(){
return balance;
}
synchronized public int withdraw(int w)
{
int b = getBalance();
if(w <= b){
balance = balance-w;
return w;
}
else
return 0;
}
}
class WithdrawAccount implements Runnable{
private BankAccount acc;
private int amount;
public WithdrawAccount(){
acc = null;
amount = 0;
}
public WithdrawAccount(BankAccount acc,int amount){
this.acc = acc;
this.amount = amount;
}
public void run() {
int w;
for(int i =0; i<20; i++){
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Balance before "+Thread.currentThread().getName()+" withdrawl: "+acc.getBalance());
w = acc.withdraw(amount);
System.out.println("Balance after "+Thread.currentThread().getName()+" withdrawl: "+acc.getBalance());
//System.out.println("amount with drawn by: "+Thread.currentThread().getName()+" "+w);
}
}
}
public class TestBankAccount{
public static void main(String[] args) {
BankAccount b = new BankAccount(1000);
WithdrawAccount w = new WithdrawAccount(b,10);
Thread wt1 = new Thread(w);
wt1.setName("T1");
Thread wt2 = new Thread(w);
wt2.setName("T2");
wt1.start();
wt2.start();
}
}
You’ve done nothing to synchronize your run method, so the printlns before and after the withdrawal and the withdrawal itself are not atomic. You’re getting thread interleaving.