2010-08-15 17 views
4

J'essaie de comprendre plus en profondeur la concurrence dans Haskell. J'ai le code suivant:Comportement des E/S simultanées Haskell

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() 

Parfois, je vois que les opérations d'impression se chevauchent et je les résultats de suivi (voir le deuxième appel):

*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> 

Je ne comprends pas pourquoi cela se passe . Pour utiliser le MVar pour [1..9] fonctionne mal aussi.

+1

En relation: http://stackoverflow.com/questions/2981984/ – sdcvvc

+0

Le problème est le thread principal terminé plus tôt que les threads enfants. Si nous attendons tous les fils enfants Aucun chevauchement n'apparaît. – Anton

+0

Aussi, 'print' =' putStrLn.show'. 'print.show' appelle' show' deux fois, ce qui est un peu redondant. – jrockway

Répondre

4

Parfois, je vois que les opérations d'impression chevauchent

La sortie chevauche parfois parce qu'il ya un verrou sur la sortie standard. Chaque thread appelle "print", qui tente d'écrire un caractère, en prenant le verrou pour chaque personnage. En raison de la concurrence préemptive de Haskell, vous verrez des entrelacements aléatoires d'impression de fils.

S'il s'agit d'un comportement indésirable, chaque thread doit envoyer la chaîne qu'il souhaite imprimer à un thread d'imprimante, qui à son tour effectuera une sortie ligne par ligne séquentielle.

+0

Comme je vous comprends haskell stdout imprimer chaque chaque caractère dans un fil séparé? Ai-je raison ? – Anton