Pergunta

Este é apenas um hipotético cenário para ilustrar a minha pergunta.Suponha que há dois threads e uma TVar compartilhado entre eles.Em um segmento há um atomicamente bloco que lê o TVar e leva 10 segundos para concluir.Em outro thread é um atomicamente bloco que modifica o TVar a cada segundo.Será a primeira atomicamente bloco nunca completa?Certamente ela só vai manter a voltar para o início, porque o log está perpetuamente em um estado inconsistente?

Foi útil?

Solução

Como outros disseram: Em teoria, não há garantia de progresso. Na prática, também não há garantia de 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"

Os acima nunca dizem "feito com STM longo" nos meus testes.

Obviamente, se você acha que o cálculo ainda será válido/pertinente, então você gostaria de

  1. Deixe o bloco atômico, execute a computação cara, digite o bloco atômico / confirmões, as suposições são válidas / e atualize o valor. Potencialmente perigoso, mas não mais do que a maioria das estratégias de travamento.
  2. Memoose os resultados no bloco atômico para que o resultado ainda válido não passasse mais do que uma pesquisa barata após uma tentativa.

Outras dicas

O STM evita o impasse, mas ainda é vulnerável à fome. É possível em um caso patológico que a ação atômica 1S sempre adquira o recurso.

No entanto, as mudanças disso que acontecem são muito raras - não acredito que já tenha visto isso na prática.

Para a semântica, veja Transações de memória composta, Seção 6.5 "Progresso". O STM em Haskell garante apenas que uma transação em execução se comprometa com sucesso (ou seja, nenhum impasse), mas, na pior das hipóteses, uma transação infinita bloqueará outras.

Não, ele não funcionará correctamente.Exatamente como os dois segmentos interagem depende de a lógica de repetição.

Por exemplo, digamos que você tem:

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

Assim, a "ten"thread vai ser em estado de repetição até que o TVar atinge o valor 7, em seguida, proceder-se-á.

Observe que você não pode controlar diretamente quanto tempo estes cálculos vai demorar dentro do STM mônada.O que seria um efeito colateral, e os efeitos colaterais não são permitido no STM cálculos.A única maneira de se comunicar com o exterior o mundo é através de valores passados através de memória transacional.

E isso significa que se o "bastão de passagem" lógica através de memória transacional é correto, o programa irá funcionar correctamente, independentemente da quantidade exata de momento, qualquer parte da demora.Essa é a parte da garantia do STM.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top