-
27-09-2019 - |
質問
これは私の質問を説明するための単なる仮説的なシナリオです。2 つのスレッドと 1 つの TVar がそれらの間で共有されているとします。1 つのスレッドには、TVar を読み取るアトミックなブロックがあり、完了するまでに 10 秒かかります。別のスレッドには、TVar を毎秒変更するアトミックなブロックがあります。最初のアトミックブロックは完成するでしょうか?ログが常に不整合な状態にあるため、最初に戻り続けるだけなのでしょうか?
解決
他の人も言っているように:理論的には進歩の保証はありません。実際には、進歩の保証もありません。
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 で完了」とは決して言われませんでした。
明らかに、計算がまだ有効/適切であると思われる場合は、次のいずれかを行う必要があります。
- アトミック ブロックを離れ、負荷の高い計算を実行し、アトミック ブロックに入り、仮定が有効であることを確認し、値を更新します。潜在的に危険ですが、ほとんどのロック戦略と同様です。
- 結果をアトミック ブロックにメモ化し、再試行後の有効な結果が単なる検索にすぎなくなるようにします。
他のヒント
STM防止デッドロックが、それでも飢餓に対して脆弱です。それは、常にリソースをAQUIREに1秒アトミックアクションの病的な場合に可能である。
しかし、この出来事の変化は非常に稀である - 。私は私が今まで実際にそれを見てきたとは思わない。
の意味については、構成可能メモリトランザクションは、セクション6.5「進捗状況」をを。 HaskellではSTMは、実行中のトランザクションが正常(すなわち、デッドロック)コミットしていないでしょうが、最悪の場合には無限のトランザクションが他の人をブロックすることのみを保証します。
いいえ、それは罰金を動作します。 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の計算に許さ。外部と通信するための唯一の方法 世界はトランザクショナルメモリを通過した値を経由している。
そして、トランザクショナルメモリ経由であれば「バトン渡し」の論理があることを意味しています 正しい、プログラムは独立して正確な量の正常に動作します 時間のその一部を取ります。それは、STMの保証の一部です。