Haskell STM:如何根据线程的执行顺序存储线程ID

Haskell STM:如何根据线程的执行顺序存储线程ID,haskell,stm,Haskell,Stm,在以下程序中,斐波那契数由给定整数(随机生成)生成,该值存储在TVar中。由于生成Fibonacci的执行时间对于不同的数目是不同的,因此线程不会按顺序运行我想将theadID存储在列表中,以检查其执行模式。 请帮帮我。提前谢谢 module Main where import Control.Parallel import Control.Concurrent.STM import Control.Concurrent import System.Random import Control.

在以下程序中,斐波那契数由给定整数(随机生成)生成,该值存储在TVar中。由于生成Fibonacci的执行时间对于不同的数目是不同的,因此线程不会按顺序运行我想将theadID存储在列表中,以检查其执行模式。 请帮帮我。提前谢谢

module Main
where
import Control.Parallel
import Control.Concurrent.STM
import Control.Concurrent
import System.Random 
import Control.Monad
import Data.IORef
import System.IO

nfib :: Int -> Int
nfib n | n <= 2 = 1
   | otherwise = par n1 (pseq n2 (n1 + n2 ))
                 where n1 = nfib (n-1)
                       n2 = nfib (n-2)


type TInt = TVar Int


updateNum :: TInt -> Int -> STM()
updateNum n v = do x1 <- readTVar n
                   let y = nfib v
                   x2 <- readTVar n
                   if x1 == x2
                   then writeTVar n y   
                   else retry

updateTransaction :: TInt -> Int -> IO ()
updateTransaction n v = do atomically $ updateNum n v

incR :: IORef Int -> Int -> IO ()
incR r x = do { v <- readIORef r;                    
      writeIORef r (v - x) }

main :: IO ()
main = do 
    n <- newTVarIO 10
    r <- newIORef 40;
    forM_ [1..10] (\i -> do 
                     incR r i
                     ;v <- readIORef r
                     ;forkIO (updateTransaction n v)
                    )

怎么办?提前谢谢。

您想要类似的东西吗

module Main
where
import Control.Parallel
import Control.Concurrent.STM
import Control.Concurrent
import System.Random 
import Control.Monad
import Data.IORef
import System.IO

nfib :: Int -> Int
nfib n | n <= 2 = 1
   | otherwise = par n1 (pseq n2 (n1 + n2 ))
                 where n1 = nfib (n-1)
                       n2 = nfib (n-2)


type TInt = TVar Int


updateNum :: TInt -> Int -> STM()
updateNum n v = do x1 <- readTVar n
                   let y = nfib v
                   x2 <- readTVar n
                   if x1 == x2
                   then writeTVar n y   
                   else retry

updateTransaction :: TInt -> Int -> IO ()
updateTransaction n v = do atomically $ updateNum n v

incR :: IORef Int -> Int -> IO ()
incR r x = do { v <- readIORef r;                    
      writeIORef r (v - x) }

main :: IO ()
main = do 
    n <- newTVarIO 10
    r <- newIORef 40;
    forM_ [1..10] (\i -> do 
                     incR r i
                     ;v <- readIORef r
                     ;forkIO (updateTransaction n v)
                    )
updateTransaction :: TInt -> Int -> IO ()
updateTransaction n v = do
  tid <- myThreadId
  putStrLn $ "Start " ++ show tid
  atomically $ updateNum n v
  putStrLn $ "End " ++ show tid
updateTransaction :: TInt -> Int -> IO ThreadId
updateTransaction n v = do
  atomically $ updateNum n v
  myThreadId
并将
表单
更改为
表单


此外,本部分:

do
  x1 <- readTVar n
  ...
  x2 <- readTVar n
  if x1 == x2 ...

(显然,您必须让
updateNum
返回它计算的数字。)

您知道您的斐波那契实现非常慢吗?或者你想用这个函数作为测试?斐波那契函数作为测试。例如,由于Fibonacci 35将比Fibonacci 25花费更多的时间,因此线程1(Fib 35)的执行时间将比线程2(Fib 25)花费更多的时间。因此,tread2将首先执行,然后是thead1(因为“重试”)。
x1是什么让您认为
else
分支将执行?如果
x1/=x2
,GHC将自动中止交易。@Zeta,请帮我澄清我的疑问。我先将n的值存储到x1中,然后存储到x2中。我这样做是为了检查数据的不一致性,以便在此基础上写入TVar或重试。Haskell STM是否能够在数据不一致的情况下自动重试。正如我所知,在这种情况下,它应该中止。非常感谢您的答复。您正确地说x1/=x2将中止事务。事务可以执行,也可以中止并重新启动。我想根据线程的执行情况将[TreadID,FibNo]存储到所有线程的列表中。假设T1执行了Fib30、T2 Fib35、T3->32和T4->40。如果线程的提交序列像T1、T3、T2和T4,那么我想将T1-35、T3-32、T2-35、T4-40存储在一个列表中。让我试试。谢谢@MathematicalOrchid。根据你的建议,我已经修改了upateTransaction。[即
updateTransaction::MVar[(ThreadId,Int)]->TInt->Int->IO()……putMVar MVar$list++[(tid,v)]
(我想存储v而不是fib,因此进行了相应的修改).总的来说,我要声明
m来澄清:你不能决定写什么?或者你写了什么,但它没有达到你的预期?你创建了一个空的
MVar
。你需要创建一个包含
[]
的开始。
updateTransaction :: TInt -> Int -> IO ThreadId
updateTransaction n v = do
  atomically $ updateNum n v
  myThreadId
do
  x1 <- readTVar n
  ...
  x2 <- readTVar n
  if x1 == x2 ...
updateTransaction :: MVar [(ThreadId, Int)] -> TInt -> Int -> IO ()
updateTransaction mvar n v = do
  tid <- myThreadId
  fib <- atomically $ updateNum n v
  list <- takeMVar mvar
  putMVar mvar $ list ++ [(tid, fib)]