A TVar
is a mutable cell. With immutable structures no two threads can transmit modifications back and forth, so we need some notion of mutable cell to cause the effect. In particular, we have
writeTVar :: TVar a -> a -> STM ()
which creates an SMT
action replacing the value inside the mutable cell. We can sequence a few of these operations together, building a bigger and more complex STM
action, and then call
atomically :: STM a -> IO a
to atomically commit the whole STM
action at once. This is the "transactional" part of software transactional memory: other threads with their own references to these mutable cells will only ever witness the entirety of the atomically
-performed STM
action, no subparts. To achieve this Haskell might use locking, or something more clever—it's a mere implementation detail. The only thing STM
asks you be cognizant of is that the actions within your STM
block may be run repeatedly as necessary—and so side effects outside of modification of some shared memory cells are prohibited.
So how do we achieve fine-grained concurrency? Easily: we just provide more mutable cells for various threads to synchronize upon. For instance, we can read at least 3 different Map
types.
TVar (Map k v)
Map k (TVar v)
TVar (Map k (TVar v))
The first will allow concurrent threads to make modifications to the entire Map
all at once such that no partial changes are visible. The second, allows changes at any stored value, but maintains that the structure of the map itself—the choice of keys and the selection of stored values—is immutable and changes cannot be easily propagated to other threads.
The final choice, TVar (Map k (TVar v))
is the most flexible. We can make wholesale modifications to the Map
by synchronizing on the outer TVar
and we can make changes to the values stored in the map by reading down to the value-TVar
s and synchronizing on actions within them. The full set of possible semantics available for such a tree is myriad allowing both "whole Map
locking" and "individual value locking" to happen together.