Pregunta

Me quedé atascado en comprender el concepto de Atómica en STM.

Ilustrato con un ejemplo

import Control.Concurrent
import Control.Concurrent.STM
import Control.Monad
import qualified Data.Map as Map 

main :: IO ()
main =  do
    d <- atomically$ newTVar Map.empty
    sockHandler  d 

sockHandler ::  TVar (Map.Map String Int)-> IO ()
sockHandler  d = do
    forkIO $ commandProcessor  d 1
    forkIO $ commandProcessor  d 2
    forkIO $ commandProcessor  d 3
    forkIO $ commandProcessor  d 4
    forkIO (threadDelay 1000 >> putStrLn "Hello World?")

    threadDelay 10000
    return ()

commandProcessor ::  TVar (Map.Map String Int)-> Int-> IO ()
commandProcessor  d i= do
  addCommand d i
  commandProcessor  d i 

addCommand  ::  TVar (Map.Map String Int) ->Int -> IO ()
addCommand    d i = do
  succ <- atomically $ runAdd d
  putStrLn  $"Result of add in " ++ (show i)++ " " ++( show succ)

runAdd  d =do
  dl <- readTVar d
  let (succ,g)= if   Map.member "a" dl
                  then
                      (False,dl)
                  else
                      (True,Map.insert "a" 9 dl)
  writeTVar d g
  return succ

La salida de muestra sería así:

Resultado de add en 1 Verdadero resultado de add en 4 resultado falso de add en 1 falseresult of add en 2 falseresult of add in 3 false hello world? Resultado de agregar en 4 falsos

Resultado de add en 1 falseresult of add en 2 resultado falso de add en 3 resultado falso de add en 4 falso

Resultado de add en 1 resultado falso de add en 2 falseresult of add en 3 falseresult of add en 4 falso

Resultado de add en 1 resultado falso de add en 2 falseresult of add en 3 falseresult of add en 4 falso

Resultado de add en 1 resultado falso de add en 2 falseresult of add en 4 falseresult of add en 3 falso

Resultado de add en 1 resultado falso de add en 4 falseresult of add en 2 falseresult of add en 3 falso

Resultado de add en 1 falseresult of add en 4 resultado falso de add en 2 resultado falso de add en 3 falso

Resultado de add en 1 falseresult of add in 4 false

Resultado de add en 2 falseresult of add in 3 false

Resultado de add en 1 falseresult of add in 4 false

Resultado de add en 2 falseresult of add en 3 resultado falso de add en 1 resultado falso de add en 4 falso

Resultado de add en 2 falseresult of add in 3 false

Resultado de add en 1 falseresult of add in 4 false

Cuando leí atómicamente

. Esto significa que todas las operaciones dentro de la transacción completamente completadas, sin ningún otro hilo que modifique las variables que nuestra transacción está usando o falla, y el estado se vuelve a donde estaba antes de que se iniciara la transacción. En resumen, las transacciones atómicas se completan por completo, o es como si nunca se ejecutaran en absoluto.

Entonces, a la pregunta, ¿podría el "retorno" de Succ en algunos casos nunca ocurrir? Es decir, ¿podría la línea succ <- atómicamente $ runadd d putstrln $ "resultado de agregar" ++ (show i) ++ "" ++ (show succ)

Dé una salida de "resultado de agregar? I" ("como si nunca se ejecutaran en absoluto")

¿Fue útil?

Solución

Si una transacción se retrocede, lo que sucede es que su programa lo intenta nuevamente. Puedes imaginar la implementación de atomically ser algo como esto:

atomically action = do varState <- getStateOfTVars
                       (newState, ret) <- runTransactionWith action varState
                       success <- attemptToCommitChangesToTVars newState
                       if success
                         then return ret
                         else atomically action -- try again

En su caso, la transacción siempre se ejecutará y siempre se completará. Puede completarse en el segundo o tercer intento debido a los conflictos, pero eso es invisible para usted, el usuario. STM se asegura de que la acción ocurra atómicamente, incluso si lleva algunos vale antes de que pueda hacerlo con éxito.

Otros consejos

  1. threadDelay ya devuelve (), no es necesario explícitamente return () después
  2. newTVarIO es una versión concisa de atomically . newTVar.
  3. Es más legible si usas forever en lugar de llamar a ti mismo como se hace en commandProcessor.

En cuanto a su pregunta, la respuesta es "sí". Se llama Live-Lock en el que su hilo tiene trabajo por hacer, pero no puede progresar. Imagina una función realmente costosa, expensive, y una función realmente barata, cheap. Si estos operan en competir atomically Bloques en el mismo TVar entonces la función barata puede causar el expensive función para nunca completar. Construí un ejemplo para un Relacionado So Pregunta.

Sin embargo, su ejemplo de cierre no está del todo correcto, si la operación STM nunca se completa, entonces putStrLn Nunca se alcanzará y no se verá ninguna salida desde ese hilo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top