Ответ 1
MVar
, как вы сказали, ориентирован на многопоточность, тогда как IORef
может использоваться как изменяемая переменная в однопоточной программе или как конструкция синхронизации в многопоточной программе.
IORef
можно использовать вместе с atomicModifyIORef
, чтобы получить поведение сравнения и замены (CAS): писатели и читатели могут синхронизировать одно чистое значение, сохраненное в IORef
. Читатели используют readIORef
для чтения значения, а авторы используют atomicModifyIORef
для записи значения. Обратите внимание, что atomicModifyIORef
не позволяет авторам выполнять какие-либо побочные эффекты внутри критического раздела (т.е. Они могут использовать чистую функцию только при атомарном изменении значения).
MVar
позволяет реализовать произвольные критические разделы (используя withMVar
), которые могут содержать побочные эффекты. Их также можно использовать так же, как IORef
(как описано в предыдущем абзаце), но с более высокой стоимостью.
Если вам нужна интуиция для того, какой семантический IORef
реализует ее так же, как семантика CAS, Rich Hickey описывает в разговоре Clojure concurrency модель: http://www.infoq.com/presentations/Are-We-There-Yet-Rich-Hickey
Изменить: Кроме того, вы не можете запускать блокировки с помощью IORef
(но все равно может возникнуть конфликт, вызывающий повторные попытки).