Hello,

recently, I and a few colleagues have been wondering about the interaction between IORefs and MVars, and we can't seem to find any explicit documentation stating the behavior, so I was wondering if anyone might know the answer.

The question is:  is it safe to use IORefs in a multi-threaded program, provided that the uses are within a "critical section" implemented with MVars.  Here is a simple program to illustrate the situation: we have two threads, each thread takes a lock, increments a counter, then releases the lock:

> import Control.Concurrent
> import Data.IORef
> main :: IO ()
> main =
>   do lock    <- newMVar ()
>      counter <- newIORef 0
>      forkIO (thread lock counter)
>      thread lock counter
>
> thread :: MVar () -> IORef Integer -> IO a
> thread lock counter =
>   do takeMVar lock
>      value <- readIORef counter
>      print value
>      writeIORef counter (value + 1)
>      putMVar lock ()
>      thread lock counter

The question is if this program has a race condition or not, due to the use of IORefs?  More explicitly, the concern is if a write to an IORef in one thread is guaranteed to be seen by a read from the same IORef in another thread, provided that there is proper synchronization between the two.

-Iavor