В следующей программе я хочу, чтобы основной поток не выходил, пока все его дочерние потоки не завершили выполнение. Обратите внимание, что я использовал шаблоны ударов для оценки вызова Fibonacci, чтобы он возвращал оцениваемый thunk в основной поток.Haskell STM: Основная нить не завершится до тех пор, пока дочерний поток не завершит выполнение
{-# LANGUAGE BangPatterns #-}
module Main
where
import Control.Concurrent.STM
import Control.Concurrent
import System.IO
nfib :: Int -> Int
nfib n | n <= 2 = 1
| otherwise = (n1 + n2)
where n1 = nfib (n-1)
n2 = nfib (n-2)
type TInt = TVar Int
updateNum :: TInt -> Int -> STM()
updateNum n v = do writeTVar n v
updateTransaction :: TInt -> Int -> IO()
updateTransaction n v = do
atomically $ do
updateNum n v
main :: IO()
main = do
n <- newTVarIO 10
forkIO $ do
let v = 30
let !x = nfib v
updateTransaction n x
forkIO $ do
let v = 15
let !x = nfib v
updateTransaction n x
forkIO $ do
let v = 25
let !x = nfib v
updateTransaction n x
nv <- readTVarIO n
putStrLn ("Fib number of " ++ " = " ++ (show nv))
nv <- readTVarIO n
putStrLn ("Fib number of " ++ " = " ++ (show nv))
nv <- readTVarIO n
putStrLn ("Fib number of " ++ " = " ++ (show nv))
Я устал, чтобы решить эту проблему в соответствии с [ссылка] (Haskell MVar : How to execute shortest job first?). Я не знаю, правильный ли подход, а также ошибка при попытке распечатать значение TMVar. Вот код: - (NFIB такое же, как и выше)
type TMInt = TMVar Int
updateNum1 :: TMInt -> Int -> STM()
updateNum1 n v = do putTMVar n v
updateTransaction1 :: TMInt -> Int -> IO()
updateTransaction1 n v = do
atomically $ do
updateNum1 n v
main1 :: IO()
main1 = do
n <- newTMVarIO 0
forkIO $ do
let v = 30
let !x = nfib v
updateTransaction1 n x
forkIO $ do
let v = 15
let !x = nfib v
updateTransaction1 n x
forkIO $ do
let v = 25
let !x = nfib v
updateTransaction1 n x
-- t <- takeTMVar n
-- putStrLn("result: " ++ (show t))
** Ошибка заключается в следующем: -
Couldn't match type `STM' with `IO'
Expected type: IO Int
Actual type: STM Int
In the return type of a call of `takeTMVar'
In a stmt of a 'do' block: t <- takeTMVar n
Пожалуйста, помогите. Благодарю.
В этом коде выполняется несколько транзакций STM, которые выполняют одиночную запись или одну запись на 'TVar'. Это выглядит странно. Нет никаких гарантий при заказе этих писем w.r.t. считывания, поэтому любое промежуточное значение может быть считано, например. '10,10,10'. – chi
@Chi, в первом случае (с TVar), если я добавляю задержку потока, например. 'threadDelay (10^6 * 4) \t nv <- readTVarIO n putStrLn (" Fib number of "++" = "++ (show nv))', тогда он показывает последнее обновленное значение, то есть 832040 (Fib 30). В противном случае он показывает значения как 10 610 и 610 (610 - значение Fib 15) –
Это прекрасно, если ваша цель - наблюдать за последствиями условий гонки. Тем не менее, я удивляюсь, почему вы не использовали простые 'IOVar', а не' TVar', вы на самом деле не используете транзакции здесь. – chi