-1

I am learning Java multithreading. This is the the code I write.

package com.company;


public class Account  {
    private double balance = 100;

    public synchronized double getBalance() {
        synchronized (this){
            return balance;
        }
    }

    public  void setBalance(double balance) {
        this.balance = balance;
    }
    public   boolean withdraw(double amount,String name){
        if(this.getBalance()>amount){
            if(Thread.currentThread().getName().equals("customer0")){
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            this.setBalance(this.getBalance() - amount);
            System.out.println(Thread.currentThread().getName() + " withdraw " + amount);
            System.out.println("Hello,  " + Thread.currentThread().getName() + " You current balance is " + this.getBalance());

            return true;
        }
        else{
            System.out.println("Sorry, " + Thread.currentThread().getName() + ". Your current balance is " + this.getBalance() + " and you  cannot withdraw " + amount);
            //System.out.println("Welcome,  " + Thread.currentThread().getName() + " Your current balance is " + this.getBalance());

            return false;
        }
    }
}

and the main class

package com.company;

import org.omg.PortableServer.THREAD_POLICY_ID;


public class Main implements Runnable {
    Account account = new Account();
    public static void main(String[] args){
            Main main = new Main();
            for(int i= 0; i< 2; i++) {
                Thread c1 = new Thread(main, "customer" + i);
                c1.start();
            }
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "'s balance is " + account.getBalance());
        account.withdraw(60, Thread.currentThread().getName());
        //
    }
}

I put synchronized keyword at getBalance() to make sure it can be accessible only by one thread a time. But still I get the negative balance.

customer0's balance is 100.0
customer1's balance is 100.0
customer1 withdraw 60.0
Hello,  customer1 You current balance is 40.0
customer0 withdraw 60.0
Hello,  customer0 You current balance is -20.0

What did I do wrong?

Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
user454232
  • 841
  • 2
  • 10
  • 23
  • 3
    Shouldn't you be synchronizing the writes? – Ruan Mendes Jan 12 '15 at 13:48
  • 1
    On a side note, don't use `double` for precision important values like money. – Ceiling Gecko Jan 12 '15 at 13:51
  • As Juan mentioned, you should synchronize the writes instead of synchronizing the get. No need to use synchronized for getBalance – Wael Jan 12 '15 at 13:51
  • @CeilingGecko, if not double then what should one use, throw some light on that. That would be of great help – User27854 Jan 12 '15 at 13:53
  • 1
    @user2900314 `BigDecimal`, for example. – kraskevich Jan 12 '15 at 13:57
  • @ILoveCoding are you suggesting the usage of BigDecimal as it has better precision than double? or some thing else. – User27854 Jan 12 '15 at 13:59
  • @user2900314 `BigDecimal` has better precision than double, yes, because it does not work as a regular floating point would work (which `double` does). More info [in this question](http://stackoverflow.com/questions/3730019/why-not-use-double-or-float-to-represent-currency) – Ceiling Gecko Jan 12 '15 at 14:02

1 Answers1

3

I think you should be synchronizing withdraw and balance.

Your code just now could let two threads withdraw at the same time but not let them check the balance at the same time.

You only want one thread withdrawing & one thread checking the balance at one time.

(Thanks for the edit suggestions)

Kevvvvyp
  • 1,704
  • 2
  • 18
  • 38