2011-03-07 20 views
17

Tengo un pequeño problema para entender la diferencia básica entre el tipo IORef y el tipo MVar en Haskell. ¿Alguien me puede ayudar con esto? Parecen resolver el mismo problema. MVar parece estar dirigido a multihilo, pero IORef tiene la función atomicModifyIORef.¿Cuál es la diferencia entre un IORef y un MVar?

Gracias!

+2

MVars representan una abstracción tipo cola que puede tomar como máximo un elemento con semántica de bloqueo, mientras que un IORef siempre tiene un elemento en él. – hvr

Respuesta

18

MVar es, como usted dijo, dirigido a multihebra, mientras que IORef se puede usar como variable mutable en un único programa de subprocesos o como una construcción de sincronización en un programa multiproceso.

IORef se puede utilizar junto con atomicModifyIORef para obtener comparación y de intercambio en el comportamiento (CAS): los escritores y los lectores pueden sincronizar en un solo valor puro, almacenado en el IORef. Los lectores usan readIORef para leer un valor y los escritores usan atomicModifyIORef para escribir un valor. Tenga en cuenta que atomicModifyIORef no permite que los escritores realicen ningún efecto secundario dentro de la sección crítica (es decir, que solo pueden usar una función pura cuando cambien atómicamente el valor).

MVar le permite implementar secciones críticas arbitrarias (usando withMVar), que pueden tener efectos secundarios. También se pueden usar como un IORef (como se describe en el párrafo anterior), pero a un costo mayor.

Si desea una intuición para qué tipo de semántica IORef implementa su lo mismo que la semántica CAS Rich Hickey describe en una charla en el modelo de concurrencia de Clojure: http://www.infoq.com/presentations/Are-We-There-Yet-Rich-Hickey

Editar: Además, no se puede ejecutar en los puntos muertos usando IORef (pero aún puede haber contención, lo que provoca reintentos).

+0

Implementé un conjunto de conexiones de bases de datos para usar en la aplicación web. Solo requiere acciones CAS y solo hay un objeto con el que trabaja: la lista de conexiones. Estoy usando MVar para mantener un Pool. ¿Recomendarías cambiarlo a IORef? Usted dice que MVar incurre en "un costo mayor". ¿Hay puntos de referencia? –

+0

Usaría un 'IORef'. Esto es lo que usamos en el administrador de E/S de GHC para almacenar un 'IntMap' que correlaciona los descriptores de archivos con las devoluciones de llamada. Recuerde que 'IORefs' (y' MVars') son flojos, por lo que tendría que hacer algo como: 'do! _ <- atomicModifyIORef ref (\ m -> let m '= insertar kvm en (m', m ') 'si desea que el resultado se evalúe en el escritor en lugar del lector. No tengo ningún punto de referencia a mano. – tibbe

Cuestiones relacionadas