2010-08-15 6 views
4

Я пытаюсь понять параллелизм в Haskell более глубоко. У меня есть следующий код:Haskell параллелизм поведение IO

import Control.Concurrent 
    main :: IO() 

    main = do 
    arr <- return $ [1..9] 
    t <- newMVar 1 
    forkIO (takeMVar t >> (print.show) arr >> putMVar t 1) 
    forkIO (takeMVar t >> (print.show) arr >> putMVar t 1) 
    forkIO (takeMVar t >> (print.show) arr >> putMVar t 1) 
    forkIO (takeMVar t >> (print.show) arr >> putMVar t 1) 
    forkIO (takeMVar t >> (print.show) arr >> putMVar t 1) 
    return() 

Иногда я вижу, что операции печати перекрывают друг друга и я получаю результаты последующих (смотрите на второй вызов):

*Main Control.Concurrent> :l test.hs 
[1 of 1] Compiling Main    (test.hs, interpreted) 
Ok, modules loaded: Main. 
*Main Control.Concurrent> main 
"[1,2,3,4,5,6,7,8,9]" 
"[1,2,3,4,5,6,7,8,9]" 
"[1,2,3,4,5,6,7,8,9]" 
"[1,2,3,4,5,6,7,8,9]" 
"[1,2,3,4,5,6,7,8,9]" 
*Main Control.Concurrent> main 
"[1,2,3,4,5,6,7,8,9]" 
"[1,2,3,4,5,6,7,8,9]" 
"[1,2,3,4,5,6,7,8,9]" 
["[1,2,3,4,5,6,7,8,9]" 
?"[1,2,3,4,5,6,7,8,9]" 
1h*Main Control.Concurrent> 

Я не понимаю, почему это происходит , Использовать MVar для [1..9] тоже плохо.

+1

Связанный: http://stackoverflow.com/questions/2981984/ – sdcvvc

+0

Проблема заключается в том, что основной поток завершен ранее, чем дочерние потоки. Если мы будем ждать все дочерние потоки, то не будет перекрываться. – Anton

+0

Кроме того, 'print' =' putStrLn.show'. 'print.show' вызывает' show' дважды, что немного избыточно. – jrockway

ответ

4

Иногда я вижу, что операции печати перекрывает

Выход иногда накладывается, потому что есть замок на стандартный вывод. Каждый поток вызывает «печать», который пытается записать один символ, используя блокировку для каждого символа. Из-за упреждающего параллелизма Haskell вы увидите случайное перемежение печати нитей.

Если это нежелательное поведение, вместо этого каждый поток отправляет строку, которую он хочет распечатать, в поток принтера, который, в свою очередь, будет выполнять последовательный линейный вывод.

+0

Как я понимаю, вы haskell stdout распечатываете каждый символ в отдельной теме? Я прав ? – Anton