haskell concurrency stm

haskell - Diferencia entre TVar y TMVar



concurrency stm (2)

He visto que el TVar es un contenedor simple, mientras que el TMVar es lo mismo que un MVar , lo que significa que tiene un bloqueo, etc., pero dentro de la mónada de STM . Me pregunto por qué sería necesario, ya que la idea del STM es hacer innecesarios los bloqueos.

Entonces, ¿cuál es el que debe usar si, por ejemplo, tiene un tipo como [Handle] una lista de identificadores de socket que desea usar entre los hilos creados por forkIO ?


Las diferencias entre TVar y TMVar no son tan grandes como parecen, definitivamente no son comparables con las diferencias entre IORef y MVar .

Si bien MVar sí proporciona cierto bloqueo para la seguridad de las TMVar , ¡ TMVar no hace nada interesante! (sin bloqueo adicional) Todo lo importante ya está implementado con STM y TVar , por lo que TMVar a es solo una abreviatura para TVar (Maybe a) equipado con algunas funciones agradables (algunas de las cuales bloquean usando la función de retry ).

Si el bloqueo con retry es compatible con el espíritu de STM y si elimina algunas de las ventajas de STM (sin interbloqueos, etc.) es una pregunta aparte y me gustaría ver a alguien con más experiencia para responderla.


No es realmente una cuestión de bloqueo, se trata de lo que significa la referencia:

  • TVar es una referencia mutable dentro de STM , que representa el estado general compartido. Lo creas con un valor, puedes leerlo y escribirlo, etc. Es muy parecido a IORef o STRef (que son lo mismo de todos modos).

  • TMVar es una referencia a un espacio que los hilos pueden usar para comunicarse. Se puede crear manteniendo un valor, o vacío. Puedes ponerle un valor, que si ya está lleno de bloques hasta que alguien más lo vacíe; o puede tomar un valor de él, que si ya está vacío bloquea hasta que alguien lo llene. Es obviamente similar a un MVar , pero para muchos usos comunes podría ser más simple pensar en él como una cola de elemento único utilizada para un par productor / consumidor comunicante.

En resumen, TVar es un estado compartido general, TVar si desea actualizaciones atómicas de datos de lugares arbitrarios. TMVar es una primitiva de sincronización, TMVar si quieres que un hilo espere hasta que algo esté disponible, mientras que otro espera que algo se necesite.

También tenga en cuenta TChan , que se implementa más o menos como dos TVar almacenamiento de TVar en una lista vinculada donde cada enlace directo también es un TVar , y funciona como una cola ilimitada para la comunicación.

Por supuesto, todos estos pueden usarse de maneras ligeramente diferentes: puede echar un vistazo al valor de un TMVar sin eliminarlo, por ejemplo, si desea un escenario donde todos los subprocesos múltiples esperen a que un solo recurso esté disponible pero es nunca "agotado".