I am currently learning synchronization in Java. As far as i understood, a synchronized instance method acquires a lock on its object.
My program is a where a 50 tasks are made and then are each given a thread. Each task adds a penny to an Account object made from an account Class.
The Account Class has a balance datafield and a synchronized method for depositing. The 50 tasks have an account field that would point to the same account object (i.e. share the account). Once the run is invoked, each task will invoke the account.deposit instance method to deposit 1 unit.
I expect the balance to end with 50 units. Surprisingly, the account ends up with 50 sometimes or other balances 14, 48, 33 etc.
class JavaStudy {
public static void main(String[] args){
for (int j = 0; j < 10; j++) {
Account account = new Account();
ExecutorService executorPool = Executors.newFixedThreadPool(50);
for (int i = 0; i < 50; i++) {
executorPool.execute(new DepositTask(account));
}
executorPool.shutdown();
while(!executorPool.isShutdown()){
}
System.out.println(account.getBalance());
}
}
}
Deposit task class !
class DepositTask implements Runnable {
private Account account;
DepositTask(Account account){
this.account = account;
}
@Override
public void run() {
account.deposit(1);
}
}
Account Class !
class Account {
private int balance = 0;
synchronized public void deposit(int amount){
int balance = this.balance + amount;
this.balance = balance;
}
String getBalance(){
return "Balance: " + balance;
}
}
According to what i understood, to what i understood the account should get locked once a task accesses account.deposit(1); .The other tasks should not be able to access it since they are sharing the same object! Somehow this is not going and i am ending up with the result below,
Balance: 20
Balance: 47
Balance: 50
Balance: 42
Balance: 27
Balance: 24
Balance: 50
Balance: 29
Balance: 13
Balance: 12
Process finished with exit code 0
Any ideas on what is going on?
I suspect you are not waiting for termination which is different to shutdown. This could mean not all the tasks have been performed.
executorPool.shutdown();
executorPool.awaitTermination(1, TimeUnit.MINUTES);
System.out.println(account.getBalance());
BTW In Java 8 you can simplify this with
Account account = new Account();
InStream.range(0, 50).parallel()
.forEach(i -> account.deposit(1));
System.out.println(account.getBalance());