2010-06-13 4 views
13

Это всего лишь гипотетический сценарий, иллюстрирующий мой вопрос. Предположим, что между ними есть два потока и один TVar. В одном потоке есть атомный блок, который читает TVar и забирает 10 секунд. В другом потоке есть атомный блок, который каждую секунду изменяет TVar. Будет ли первый атомный блок когда-либо закончен? Несомненно, он просто вернется к началу, потому что журнал постоянно находится в противоречивом состоянии?Проблема монады STM

ответ

12

Как говорили другие: в теории нет гарантии прогресса. На практике нет также никакой гарантии прогресса:

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" 

выше никогда не говорит: «Совершено с длинными СТМ» в моих тестах.

Очевидно, что если вы думаете, что вычисление по-прежнему будет иметь силу/уместно, то вы хотите, будете либо

  1. Оставьте атомный блок, выполнять дорогостоящее вычисление, введите атомный блок/подтвердить предположение верно и/обновите значение. Потенциально опасный, но не более, чем большинство стратегий блокировки.
  2. Запомните результаты в атомном блоке, чтобы по-прежнему действительный результат был не более чем дешевым поиском после повтора.
+2

Отличный пример. Я хотел протестировать что-то вроде этого, но я не знал о функции 'unsafeIOToSTM'! – Alex

2

Нет, все будет хорошо. Точно так же, как взаимодействуют два потока, зависит от логики повторения логики .

Например, предположим, что у вас есть:

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 

Так что «ten» поток будет находиться в состоянии повторной попытки до тех пор, пока не достигнет TVAR значение 7, то это будет продолжаться.

Обратите внимание, что вы не можете напрямую контролировать, как долго эти вычисления будут принимать внутри монадии STM. Это будет побочным эффектом, а побочные эффекты не являются допустимыми в расчетах STM . Единственный способ общения с внешним миром - это через значения, переданные через транзакционную память.

А это означает, что если логика «baton-прохождения» через транзакционную память правильная, программа будет работать правильно независимо от точной суммы времени, когда любая ее часть занимает. Это часть гарантии STM.

+0

Я действительно думаю о худшем случае. Давайте забудем ретрос на мгновение и просто подумаем о двух потоках и рассмотрим исполнение STM «десять». Он читает TVar и записывает это значение в журнал. Между тем, другая нить меняет, что TVar всегда во время исполнения «десять».Таким образом, в конце выполнения «десятки» значение в реальном TVar не совпадает с значением, первоначально прочитанным в «десяти», заставляя «десять» повторно инициализировать журнал и повторно выполнять каждый раз. – Alex

+1

Как сказал Иц, это зависит. Да, можно построить ситуацию, когда транзакция никогда не завершится. Более формально STM не гарантирует прогресс. –

5

STM предотвращает тупик, но по-прежнему уязвим для голода. В патологическом случае, когда атомное действие 1s всегда будет обладать ресурсом, возможно.

Однако изменения этого происшествия очень редки - я не верю, что когда-либо видел это на практике.

Для семантики см. Composable Memory Transactions, раздел 6.5 «Прогресс». STM в Haskell гарантирует только успешную транзакцию транзакции (т. Е. Без взаимоблокировки), но в худшем случае бесконечная транзакция блокирует другие.

+0

Спасибо за ссылку. – Alex

+0

STM не обязательно не блокируются. –