STM Monad проблема
-
27-09-2019 - |
Вопрос
Это просто гипотетический сценарий, чтобы проиллюстрировать мой вопрос. Предположим, что между ними разделяется два потока и один из телевизоров. В одном потоке имеется атомчески блок, который читает телевизор и занимает 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"
Вышеупомянутое никогда не говорит «сделано с длинным СТМ» в моих тестах.
Очевидно, что если вы думаете, что вычисления все еще будут действительными / соответствующими, то вы хотели бы либо
- Оставьте атомный блок, выполните дорогие вычисления, введите атомные блок / подтверждение допущений действительны / и обновите значение. Потенциально опасно, но не более чем большинство стратегий блокировки.
- Воспоминание Результаты в атомном блоке, чтобы все еще действующий результат будет не более дешевым поиском после повторения.
Другие советы
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.