- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在以下程序中,斐波那契数是根据给定的整数(随机生成)生成的,并将该值存储到 TVar 中。由于不同数字生成斐波那契数的执行时间不同,因此线程不会顺序运行。 我想存储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)
)
我想根据所有线程的执行将 [TreadID,FibNo] 存储到一个列表中。假设T1执行了Fib30,T2执行了Fib35,T3->32和T4->40。如果线程的提交顺序如 T1、T3、T2 和 T4,那么我想将 T1-35、T3-32、t2-35、t4-40 存储在列表中。
编辑:根据@MathematicalOrchid的建议,我修改了 updateTrasaction 如下:-
updateTransaction :: MVar [(ThreadId, Int)] -> TInt -> Int -> IO ()
updateTransaction mvar n v = do
tid <- myThreadId
atomically $ updateNum n v
list <- takeMVar mvar
putMVar mvar $ list ++ [(tid, v)]
现在我正在尝试打印 main 中该列表中的值
main :: IO ()
main = do
...
...
m <- newEmptyMVar
...
...
mv <- readMVar m
putStrLn ("ThreadId, FibVal : " ++ " = " ++ (show mv))
执行时。无法读取 MVar 值并生成错误
Exception: thread blocked indefinitely in an MVar operation
该怎么办?提前致谢。
最佳答案
你想要类似的东西
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
并将 forM_
更改为 forM
?
另外,这部分:
do
x1 <- readTVar n
...
x2 <- readTVar n
if x1 == x2 ...
如果x1/= x2
,那么 GHC 将自动中止并重新启动您的交易。您不需要自己手动检查这一点。事实上,else 分支永远无法执行。这就是 STM 的要点;对于您的事务来说,没有其他人更改您正在查看的数据,因此您不必担心并发写入。
编辑:如果您想记录事务提交的实际顺序,您将需要更多的线程间通信。显然你可以用 STM 做到这一点,但只是为了列出一些东西,也许这可以工作?
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)]
(显然你必须让 updateNum
返回它计算出的数字。)
关于 haskell STM : How to store ThreadID as per their execution sequence,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27273370/
我是一名优秀的程序员,十分优秀!