🎓 A1Learner
🔍
0 of 47 lessons completed

Haskell STM Idea

Software transactional memory is a way to change shared boxes together, as one step. It lets threads share data without holding a lock by hand.

One TVar change lands as a single step

Start with 10. Add 5 inside one transaction.

import Control.Concurrent.STM

main :: IO ()
main = do
  t <- newTVarIO (10 :: Int)
  atomically $ modifyTVar' t (+ 5)
  v <- readTVarIO t
  print v

Two boxes change together

Start with 10 and 20. Change both inside one transaction.

import Control.Concurrent.STM

main :: IO ()
main = do
  a <- newTVarIO (10 :: Int)
  b <- newTVarIO (20 :: Int)
  atomically $ do
    modifyTVar' a (+ 3)
    modifyTVar' b (+ 4)
  x <- readTVarIO a
  y <- readTVarIO b
  print (x, y)

A flag and a count change together

Start with a count of 0 and a flag of False. Set both inside one transaction.

import Control.Concurrent.STM

main :: IO ()
main = do
  count <- newTVarIO (0 :: Int)
  flag <- newTVarIO False
  atomically $ do
    writeTVar count 5
    writeTVar flag True
  c <- readTVarIO count
  f <- readTVarIO flag
  print (c, f)

Example

import Control.Concurrent.STM

main :: IO ()
main = do
  a <- newTVarIO (100 :: Int)
  b <- newTVarIO (50 :: Int)
  atomically $ do
    modifyTVar' a (subtract 30)
    modifyTVar' b (+ 30)
  x <- readTVarIO a
  y <- readTVarIO b
  print (x, y)

Key points

  • STM: software transactional memory changes shared boxes as one step.
  • Shared box: a box that more than one thread can read and change.
  • Transaction: a group of reads and writes that happens all at once or not at all.
  • Atomically: the function atomically runs a transaction so no other thread sees it half done.
  • Conflict: two transactions clash when they change the same box at the same time.

In this example, two accounts start at 100 and 50. One transaction takes 30 from the first and adds 30 to the second. The main thread reads both back and prints 70 and 80.

Note

STM retries a clashing transaction instead of locking the box by hand.

Try it Yourself

Edit the code, then press Run.

Running is simulated · Haskell Playground

Exercise

What does atomically guarantee about a transaction?