Вопрос

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

Это было полезно?

Решение

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

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. Воспоминание Результаты в атомном блоке, чтобы все еще действующий результат будет не более дешевым поиском после повторения.

Другие советы

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

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

Для семантики см. Компонентные операторы памяти, Раздел 6.5 «Прогресс». STM в Haskell гарантирует только то, что бегущая транзакция успешно завершится (т.е. нет тупика), но в худшем случае бесконечная транзакция блокирует других.

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

Например, скажем, у вас есть:

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.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top