Проблема монады STM - PullRequest
       22

Проблема монады STM

13 голосов
/ 13 июня 2010

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

Ответы [ 3 ]

12 голосов
/ 14 июня 2010

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

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"

Вышеприведенное никогда не говорит "Готово с длинным STM" в моих тестах.

Очевидно, если вы думаете, что вычисления все еще будутдопустимо / уместно, тогда вы захотите либо

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

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

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

Семантика приведена в Операции с составной памятью , раздел 6.5 «Ход выполнения». STM в Haskell гарантирует только то, что выполняющаяся транзакция будет успешно зафиксирована (т.е. без тупиков), но в худшем случае бесконечная транзакция заблокирует другие.

2 голосов
/ 13 июня 2010

Нет, все будет работать нормально. Как именно будут взаимодействовать два потока, зависит от логика повторения.

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

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.

...