Every repository with this icon (
Every repository with this icon (
Reference: Software Transactional Memory (STM)
Transactors: Software Transactional Memory (STM)
An STM turns the Java heap into a transactional data set with begin/commit/rollback semantics. Very much like a regular database. It implements the first three letters in ACID: ACI . E.g.
- Atomic
- Consistent
- Isolated
Transactors: Software Transactional Memory (STM) module
Actors are excellent for solving of problems where you have many independent processes that can work in isolation and only interact with other Actors through message passing. This model fits many problems. But the actor model is unfortunately a terrible model for implementing truly shared state. E.g. when you need to have consensus and a stable view of state across many components. The classic example is the bank account to clients to deposits and withdrawals in which each operation needs to be atomic. For detailed discussion on the topic see this JavaOne presentation.
STM on the other hand is excellent for problems where you need consensus and a stable view of the state by providing compositional transactional shared state. Some of the really nice traits of STM is that transactions compose and that it raises the abstraction level from lock-based concurrency.
Akkas’ Transactors, e.g. being able to optionally combine Actors and STM provides IMHO the best of the Actor model (concurrency and asynchronous event-based programming) and STM (compositional transactional shared state) by providing transactional, compositional,
asynchronous, event-based message flows.
If you need the Durability then you should not use one of the in-memory data structures but one of the persistent ones.
Overview of the STM
Akka’s STM implements the concept in Clojure’s STM view on state in general. Please take the time to read this excellent document and view this presentation by Rich Hickey (the genius behind Clojure), since it forms the basis of Akka’s view on STM and state in general.
It is based on two concepts:
- Persistent Datastructures: Immutable but with constant time access and modification. The use structural sharing and and an insert or update does not ruin the old structure, hence “persistent”.
- Managed References: Memory cells, holding an immutable value, that implement CAS (Compare-And-Swap) semantics and are managed and enforced by the STM for coordinated changes across many References.
The Persistent Datastructures consists of a Map and Vector and are Scala ports of Clojure’s Map and Vector.
The Managed References are implemented using the excellent Multiverse STM.
Managed datastructures
Akka provides three different datastructures that are managed by the STM.
- Map
- Vector
- Ref
The Map and Vector looks like regular mutable datastructures, they even implement the standard Scala Map and RandomAccessSeq interfaces. But they are implemented using persistent datastructures and managed references under the hood. Therefore safe to use in a concurrent environment. They are can only be modified inside the scope of a STM transaction (see below for details).
Here is how you create these:
// Scala version val map = TransactionalState.newMap[String, Person] val vector = TransactionalState.newVector[Address] val ref = TransactionalState.newRef[Account]
How to disable the STM?
By default the STM is always turned on. This means that Actors and Active Objects will have the transaction semantics of “transaction supports”. E.g. they will happily join an existing transaction but not start a new one.
If you would like to completely turn off the STM since you know that you are not using any Transactional datastructures at all then you can either invoke:
// Scala version TransactionManagement.disableTransactions
Or you can turn it off in the ‘akka.conf’ configuration file. See the section on the configuration file for details.
Turning it off with yield better performance since the STM adds a certain overhead with its bookkeeping.
Starting new transactions
You can define an Active Object and Actor to have “transaction required” semantics. This means that if it is invoked outside the scope of a transaction then a new transaction will always be started, but if it already is in a transaction then that transaction will be joined.
Java API: Active Objects
Transaction required semantics for an Active Object is defined by adding the ‘@se.scalablesolutions.akka.annotation.transactionrequired’ annotation to the class:
@transactionrequired
class POJO {
...
}
Scala API: Actors
Transaction required semantics for an Actor is defined by invoking the ‘makeTransactionRequired’ method:
class MyActor extends Actor {
makeTransactionRequired
...
}






