If I share an IORef among multiple threads, and use atomicModifyIORef to write to it:
atomicModifyIORef ref (\_ -> (new, ()))
Is it safe to read the value with plain old readIORef? Or is there a chance readIORef will return the old value in another thread after atomicModifyIORef has modified it?
I think that’s what the documentation implies:
atomicModifyIORef acts as a barrier to reordering. Multiple
atomicModifyIORef operations occur in strict program order. An
atomicModifyIORef is never observed to take place ahead of any earlier
(in program order) IORef operations, or after any later IORef
operations.
I just want to be sure.
atomicModifyIORefguarantees that nothing happens between the atomic read and the following atomic write, thus making the whole operation atomic. The comment that you quoted just states that noatomicModifyIORefs will ever happen in parallel, and that the optimizer won’t try to reorder the statements to optimize the program (separate reads and writes can safely be moved around in some cases; for example ina' <- read a; b' <- read b; write c $ a' + b', the reads can safely be reordered)readIORefis already atomic, since it only performs one operation.However, you are discussing a different issue. Yes, if the
atomicModifyhappens att=3msand thereadhappens att=4ms, you will get the modified value. However; threads aren’t guaranteed to run in parallel, so if you do (pseudocode):… there’s no guarantee that the read will happen after the modify (it’s extremely unlikely on modern OS’s, though), because the operating system might decide to schedule the new short-lived thread in such a way that it doesn’t happen in parallel.