Search code examples
javafunctional-programmingmutable

Java: state sharing between threads in functional programming


My question is a more specific instantiation of this question: Functional programming: state vs. reassignment

I'm a newbee to FP and trying to understand it through Java.

I have the following class whose object is shared between multiple threads:

public class Bank
{
    private double[] accounts = new double[1000];

    public synchronized void transfer(int from, int to, double amount)
    {
        account[from] -= amount;
        account[to] += amount;
    }
}

(This is a very simplified example, hence other details such as validation and condition waiting are omitted).

Because 'transfer' method is synchronized, Bank object's mutable state won't be corrupted even if it's shared with multiple threads. If I want to achieve the same thing through FP in Java, how would I write that code? (I would like to see an actual code example).

EDIT: my interest in FP stems from its potential for writing thread-safe, concurrent applications. Following is a link to an article that claims it: http://www.defmacro.org/ramblings/fp.html

EDIT2: just found out about an STM for Java. Not sure about its performance, but it seems to provide what I wanted. http://multiverse.codehaus.org/60second.html


Solution

  • There are many ways to approach your shared, synchronized state variable in a more functional way.

    Transactional variables

    The classic approach here is to use transactional memory:

    you have precisely one shared state variable in the program, supporting rollback on conflicting writes. In Haskell, this would be represented via a TVar (transaction variable), in the STM monad (a monad that supports state only via transactional variables).

    The benefit of using STM here is that you can guarantee deadlock avoidance (though livelock is still possible).

    Memory Variables

    You can also use more traditional approaches such as MVars. These are mutable variables that behave as locks:

    • they contain only one value
    • that value may be removed or put into the variable
    • if a thread tries to write to a full MVar, it blocks
    • if a thread tries to read from an empty MVar, it blocks

    In this way you can support threads updating the shared value atomically.

    I'd go for the STM solution, since that's the most idiomatic.