Domanda

Questa è solo un ipotetico scenario per illustrare la mia domanda. Supponiamo che ci siano due fili e una Tvar comune tra loro. In un thread c'è un atomicamente blocco che legge il Tvar e prende 10s al completo. In un altro filo è un atomicamente blocco che modifica il Tvar ogni secondo. Sarà la prima atomicamente blocco mai completare? Sicuramente sarà solo continuare ad andare di nuovo all'inizio, perché il registro è perennemente in uno stato incoerente?

È stato utile?

Soluzione

Come altri hanno detto: in teoria non v'è alcuna garanzia di progresso. In pratica v'è inoltre alcuna garanzia di progresso:

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"

È possibile che questo non dice mai "Fatto con lunghi STM" nel mio test.

Ovviamente se si pensa che il calcolo è ancora in corso di validità / pertinenti allora si vorrebbe o

  1. Lascia il blocco atomica, eseguire costosi calcolo, entrano le atomiche ipotesi di blocco / conferma sono validi / e aggiornare il valore. Potenzialmente pericoloso, ma non più di quanto la maggior parte delle strategie di blocco.
  2. Memoize i risultati nel blocco atomica in modo che il risultato ancora valido non sarà più di una ricerca a buon mercato dopo un ulteriore tentativo.

Altri suggerimenti

impedisce STM situazione di stallo, ma è ancora vulnerabile alla fame. E 'possibile in un caso patologico per i 1s azione atomica di acquisire sempre la risorsa.

Tuttavia, i cambiamenti che ciò accada sono molto rare - non credo che abbia mai visto in pratica

.

Per la semantica, vedi Componibile Le operazioni di memoria , sezione 6.5 "Progress". STM in Haskell garantisce solo che una transazione in esecuzione commetterà con successo (vale a dire senza deadlock), ma nel peggiore dei casi una transazione infinita bloccherà altri.

No, che avrebbe funzionato bene. Esattamente come i due fili potrebbero interagire dipende la logica di tentativo.

Per esempio, diciamo che avete:

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

Quindi, la discussione "ten" sarà in stato di tentativo fino a quando raggiunge Tvar il valore 7, poi si procederà.

Si noti che non si può controllare direttamente quanto tempo questi calcoli prenderanno all'interno monade STM. Questo sarebbe un effetto collaterale, e gli effetti collaterali non sono consentito nei calcoli STM. L'unico modo per comunicare con l'esterno mondo è tramite valori passati attraverso la memoria transazionale.

E questo significa che se la logica "testimone-passa" attraverso la memoria transazionale è corretto, il programma funziona correttamente indipendentemente dalla quantità esatta di tempo una parte di esso prende. Questo fa parte della garanzia di STM.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top