0

I completely new to multithreading in Java. But I'm trying to create a method that is multithreaded and thread-safe and below is what I've come up with so far. This method can be called with the same account with either the source or destination arguments in different threads. So for example thread 1 with an account maybe the source, while thread 2 may be the destination of this transfer. Can anyone point me in the right direction. I've looked at this post: Java Multithreading : How to make a thread wait ? and other articles on the web explaining how synchronized works and my assumption is that by putting synchronized around the below code block will lock the process until it has completed. Then the other threads can pick up afterward and process the rest. I apologize in advance for my ignorance on this topic. I'm just hoping someone could put me in the right direction. There's a lot of information to go through and I'm just hoping for some expert guidance. Thanks in advance

public static void transfer(BankAccount  source, BankAccount destination, int amount) {
    if (source.getAvailableFunds() >= amount) {
        synchronized (BankAccount.class) {
            source.setAvailableFunds(source.getAvailableFunds() - amount);
            destination.setAvailableFunds(destination.getAvailableFunds() + amount);
        }
    } else {
        throw new IllegalArgumentException("No funds in source: " + source);
    }

}
Community
  • 1
  • 1
hackthisjay
  • 177
  • 4
  • 22

1 Answers1

0

What do you mean by source and destination in different threads?

As this is an static method, you could call it public synchronized static void transferand remove the syncronized block from inside. Again, being an static method assures you that this method on this class will not be executed concurrently in your JVM.

public syncronized static void transfer(BankAccount  source, BankAccount destination, int amount) {
    if (source.getAvailableFunds() >= amount) {
        source.setAvailableFunds(source.getAvailableFunds() - amount);
        destination.setAvailableFunds(destination.getAvailableFunds() + amount);
    } else {
        throw new IllegalArgumentException("No funds in source: " + source);
    }
}

This way source.getAvailableFunds() >= amount will never conflict with other thread changing the AvailableFunds at the same time.

Netto
  • 284
  • 2
  • 10
  • 1
    Note that *Synchronization* isn't *transitive*. So, other threads can change the data and cause inconsistencies if you have not taken care to *synchronize all critical sections*. – TheLostMind Jan 08 '15 at 05:36
  • 1
    That is right. For a complete control of the `funds` movements synchronization, all possible operations should be handled in one single synchronized piece of code. – Netto Jan 08 '15 at 05:40
  • 1
    `being an static method assures you that this method on this class will not be executed concurrently in your JVM` is incorrect - there is no guarantee that a static method cannot be executed concurrently. Also, the fact that the whole method is synchronized does not mean that `will never conflict with other thread changing the AvailableFunds at the same time` - it merely guarantees that no other thread can execute the same block of code at the same time. There can still be another block of code which changes the same BankAccount object fields at the same time. – xpa1492 Jan 08 '15 at 05:44
  • @xpa1492 - I agree with you. *Synchronization* is a *code level* concept. Not an *object* level concept. – TheLostMind Jan 08 '15 at 05:48
  • Ok, maybe I wasn't clear enough. But the caller of transfer method is multithreaded and may call the transfer method with the same bank account as either being the source or the destination argument from different threads. For example, thread 1, account #1 may be the source while thread 2 it may be the destination of a transfer. I need to make the transfer method thread safe. Is it as simple as adding synchronized to this static method? Or should I actually synchronize the setAvailableFunds method. Does that makes sense? Really appreciate the responses. – hackthisjay Jan 08 '15 at 05:58
  • Short answer is 'yes' for the `transfer` method. But if you have another method `withdraw` which might be called at the same time as transfer on the same BankAccount object, then you have a problem. – xpa1492 Jan 08 '15 at 06:02
  • Synchronizing the `setAvailable` funds wouldn't make a tranfer safe either, considering you have other code that change the funds. The safeness is to guarantee that without concurrency, the money will enter 1 account and leave the other at the same time. I saw it the simplest way. – Netto Jan 08 '15 at 06:09
  • @xpa1492 in that scenario you describe. Wouldn't just adding synchronized to the withdraw method solve the issue? Or is there a little more to it than that. Should I synchronized the BankAccount object to prevent that issue? – hackthisjay Jan 08 '15 at 06:09
  • To simplify. never call `getAvailableFunds`nor `setAvailableFunds` outside a `synchronized(BankAccount.class)`block, and you should be fine – Netto Jan 08 '15 at 06:12