質問

私はSTMの原子的な概念を理解することに閉じ込められました。

例で説明します

import Control.Concurrent
import Control.Concurrent.STM
import Control.Monad
import qualified Data.Map as Map 

main :: IO ()
main =  do
    d <- atomically$ newTVar Map.empty
    sockHandler  d 

sockHandler ::  TVar (Map.Map String Int)-> IO ()
sockHandler  d = do
    forkIO $ commandProcessor  d 1
    forkIO $ commandProcessor  d 2
    forkIO $ commandProcessor  d 3
    forkIO $ commandProcessor  d 4
    forkIO (threadDelay 1000 >> putStrLn "Hello World?")

    threadDelay 10000
    return ()

commandProcessor ::  TVar (Map.Map String Int)-> Int-> IO ()
commandProcessor  d i= do
  addCommand d i
  commandProcessor  d i 

addCommand  ::  TVar (Map.Map String Int) ->Int -> IO ()
addCommand    d i = do
  succ <- atomically $ runAdd d
  putStrLn  $"Result of add in " ++ (show i)++ " " ++( show succ)

runAdd  d =do
  dl <- readTVar d
  let (succ,g)= if   Map.member "a" dl
                  then
                      (False,dl)
                  else
                      (True,Map.insert "a" 9 dl)
  writeTVar d g
  return succ

サンプル出力は次のようになります。

追加の結果の1つの真の結果の追加結果の4つの偽の結果を追加する1つのfalseresult of add in 2 falseresult of add in 3 false hello world? 4 falseの追加の結果

追加の結果1 falserest of add in 2 false add in 3 false add in fals

追加の結果1のaddのaddの2 falseresult in 3 falseresult in add in 4 fals

追加の結果1のaddのaddの2 falseresult in 3 falseresult in add in 4 fals

追加の結果1のaddのaddの2 falseresult in 4 falseresult in add in 3 fals

追加の結果1のaddのadd in4 falseresult in 2 falseresult in add in 3 fals

追加の結果1 falserest of add in 4 false add in 2 false add in 3 false

追加の結果1 falseresult of add in 4 false

追加の結果2 falseresult of add in 3 false

追加の結果1 falseresult of add in 4 false

追加の結果2 falserest of add in 3 false add in add in 1 false add in 4 fals

追加の結果2 falseresult of add in 3 false

追加の結果1 falseresult of add in 4 false

原子について読んだとき

. 。これは、トランザクション内のすべての操作が完全に完了することを意味します。他のスレッドでは、トランザクションが使用している変数を変更するか、失敗し、状態はトランザクションが開始される前の場所に戻ります。要するに、アトミックトランザクションは完全に完了するか、まるでそれらがまったく実行されなかったかのようです。

それで、質問に、場合によってはサクスの「戻り」が起こらないでしょうか?それは、ラインがコセクルである可能性があります<-tomatically $ runadd d putstrln $ "add in" ++(show i)++ "" ++(show cuck)

「add in?i」の出力を与える(「まるで彼らがまったく実行されなかったかのように」)

役に立ちましたか?

解決

トランザクションがロールバックされた場合、何が起こるかが、プログラムが再び試みることです。の実装を想像できます atomically このようなものになる:

atomically action = do varState <- getStateOfTVars
                       (newState, ret) <- runTransactionWith action varState
                       success <- attemptToCommitChangesToTVars newState
                       if success
                         then return ret
                         else atomically action -- try again

あなたの場合、トランザクションは常に実行され、常に完了します。競合のために2回目または3回目の試行で完了する可能性がありますが、それはユーザーには見えません。 STMは、アクションが原子的に発生することを確認します。

他のヒント

  1. threadDelay 既にreturn()、明示的に必要ありません return () その後
  2. newTVarIO の簡潔なバージョンです atomically . newTVar.
  3. 使用すれば読みやすくなります forever テールが自分を完成させたとおりに呼ぶ代わりに commandProcessor.

あなたの質問に関しては、答えは「はい」です。それはあなたのスレッドにやるべきことがあるが、それは進歩することはできないライブロックと呼ばれています。本当に高価な機能を想像してください、 expensive, 、そして本当に安い機能、 cheap. 。これらが競合する場合 atomically 同じことにブロック TVar その後、安価な機能が原因となります expensive 決して完了しない機能。 aの例を作成しました 関連する質問.

ただし、STM操作が完了しない場合、閉鎖の例はまったく正しくありません putStrLn 決して到達することはなく、そのスレッドから出力はまったく見られません。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top