STM problema monade
-
27-09-2019 - |
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?
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
- 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.
- 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.