No atomic read on MVar?

Chris Kuklewicz haskell at
Tue Nov 4 05:57:58 EST 2008

It is true that STM's TMVars (which are TVar (Maybe _)) allow atomic readTMVar.

They are not a great replacement for MVars for serious performance reasons.

MVars have "wake one" semantics: There can be many threads stopped and waiting 
on a particular MVar to be filled/emptied.  These are actually in a FIFO queue. 
  Filling or emptying it will cause the next thread in the FIFO queue to run, 
and leave the others to sleep. [1]

TVars (and TMVars, and all STM threads) have "wake all" semantics: All threads 
which are stopped after a "retry" that are monitoring a particular TVar will be 
woken when the TVar is changed by the next STM commit.  This will cause the 
"thundering herd" problem that plagued big Apache web servers with the original 
multi-process model [2].

To understand MVars and Simon's comments on the atomic read proposal I went and 
read the code in [3] to see it first hand.  The putMVar# and tryPutMVar# 
operations, when a take operation is blocked, will perform the take operation 
and then wake the blocked thread.  The takeMVar# and tryTakeMVar# do the 
reverse.  So adding an atomicRead# operation would mean that on filling the MVar 
that all the atomicRead# that are waiting might need to be woken (or perhaps 
just those at the front of the FIFO).  This is a fairly large change.

The desire to atomically read an MVar could be expressed by
   (1) Use STM and lose the "wake one" performance
   (2) Use an (MVar ()) guarding the (MVar a)
   (3) Use an (MVar ()) guarding an (IORef a)

Where (3) has a performance advantage to (2) and (3) is safe when only the right 
operations are exposed.

I started looking at this with the opinion that "readMVar" and "withMVar" should 
have atomic semantics, i.e. edit PrimOps.cmm to add these operations.  Now I am 
leaning to taking (3) and packaging this as a new module that exposes the safe 





More information about the Glasgow-haskell-users mailing list