Pregunta

Esto es sólo un escenario hipotético para ilustrar mi pregunta. Supongamos que hay dos hilos y una TVAR compartido entre ellos. En un hilo hay un atómicamente bloque que lee el TVAR y toma 10s a completa. En otro hilo es un atómicamente bloque que modifica la TVAR cada segundo. Será la primera vez atómicamente bloque de completar? Seguramente se acaba de mantener de nuevo al principio de ir, ya que el registro está perpetuamente en un estado incoherente?

¿Fue útil?

Solución

Como han dicho otros: en teoría, no hay garantía de progreso. En la práctica, tampoco hay garantía de progreso:

import Control.Monad -- not needed, but cleans some things up
import Control.Monad.STM
import Control.Concurrent.STM
import Control.Concurrent
import GHC.Conc
import System.IO

main = do
    tv <- newTVarIO 0
    forkIO (f tv)
    g tv

f :: TVar Int -> IO ()
f tv = forever $ do
    atomically $ do
            n <- readTVar tv
            writeTVar tv (n + 1)
            unsafeIOToSTM (threadDelay 100000)
    putStr "."
    hFlush stdout

g :: TVar Int -> IO ()
g tv = forever $ do
    atomically $ do
            n <- readTVar tv
            writeTVar tv (n + 1)
            unsafeIOToSTM (threadDelay 1000000)
    putStrLn "Done with long STM"

Lo anterior no dice "Hecho con mucho STM" en mis pruebas.

Obviamente, si usted piensa que el cálculo es todavía va a ser / pertinente válida, entonces usted quiere cualquiera

  1. Deja el bloque atómica, realice el cálculo caro, entran en los supuestos de bloque y / o confirmar atómicas son válidos / y actualizar el valor. Potencialmente peligroso, pero no más que la mayoría de las estrategias de bloqueo.
  2. memoize los resultados en el bloque atómica lo que el resultado sigue siendo válido no será más que una búsqueda barato después de un reintento.

Otros consejos

previene MCI punto muerto, pero sigue siendo vulnerable a la hambruna. Es posible en un caso patológico de los 1s acción atómica a adquirir siempre el recurso.

Sin embargo, los cambios de que esto ocurra son muy raros - No creo que jamás he visto en la práctica

.

Para la semántica, consulte Composable Las operaciones de memoria , capítulo 6.5 "Progreso". STM en Haskell garantiza únicamente que una transacción en ejecución será comprometerse con éxito (es decir, no de interbloqueo), pero en el peor de los casos una transacción infinita bloqueará otros.

No, que funcionaría bien. Exactamente cómo los dos hilos haría depende interactúan en la lógica de reintento.

Por ejemplo, digamos que usted tiene:

ten tv = do
  n <- readTVar tv
  when (n < 7) retry
  writeTVar tv 0
  -- do something that takes about 10 seconds

one tv = do
  modifyTVar tv (+1)
  -- do something that takes about 1 second

Así que el hilo "ten" estará en estado de reintento hasta los confines TVAR el valor 7, a continuación, se va a proceder.

Tenga en cuenta que no se puede controlar directamente el tiempo que estos cálculos se llevarán dentro de la mónada STM. Eso sería un efecto secundario, y los efectos secundarios no son permitido en los cálculos de STM. La única manera de comunicarse con el exterior mundo es a través de valores que pasa a través de la memoria transaccional.

Y eso significa que si la lógica "bastón de mando de paso" a través de la memoria transaccional es correcta, el programa funcionará correctamente, independientemente de la cantidad exacta del tiempo de cualquier parte de ella toma. Eso es parte de la garantía de STM.

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