Software Transactional Memory (STM)

As well as Java EE compliant transactions (JTA and JTS), WildFly Swarm provides advanced transaction support through the Narayana transaction project. One of these examples is Software Transactional Memory (STM). Much more detail can be found here (http://narayana.io/docs/project/index.html) but a summary is given below for completeness.

In order to illustrate the Narayana STM implementation let’s look at one of the WildFly Swarm examples (https://github.com/wildfly-swarm/wildfly-swarm-examples/tree/master/arjuna/stm-shrinkwrap). This example will use all of the default settings for STM so it’s worth knowing that there are a lot of other things you can change when building your applications. We’ll start by creating a fairly simple STM integer object which has three methods, increment, decrement and value which do pretty much what their names imply.

@Transactional
public interface Sample {
    public void increment ();
    public void decrement ();

    public int value ();
}

The @Transactional annotation defines that implementations of the interface are to be managed within a transactional container. All public methods will be assumed to modify the state of the object, i.e., require write locks. All state variables will be saved and restored. Now we look at an implementation of this interface.

@Transactional
public class SampleLockable implements Sample {
    public SampleLockable (int init) {
        _isState = init;
    }

    @ReadLock
    public int value () {
        return _isState;
    }

    @WriteLock
    public void increment () {
        _isState++;
    }

    @WriteLock
    public void decrement () {
        _isState--;
    }

    @State
    private int _isState;
}

In the implementation we use some additional annotations to override the default values. For instance @ReadLock tells the system that the value method isn’t going to change the state of the instance so only a read lock will be obtained.

When creating instances of SampleLockable, we need to pass them to an STM container in order for it to manage the interactions with the objects. In the example (below) we create transactions (AtomicAction instances) before operating on the STM objects but that’s not strictly necessary.

Container<Sample> theContainer = new Container<Sample>("Demo", Container.TYPE.PERSISTENT, Container.MODEL.SHARED);

Sample obj1 = theContainer.create(new SampleLockable(10));
String str = "Object name: "+theContainer.getIdentifier(obj1)+"\n";

for (int i = 0; i < 10; i++) {
    AtomicAction A = new AtomicAction();

    A.begin();

    obj1.increment();

    str += "Transaction value hello" + obj1.value() + "\n";

    A.commit();
}

return str;