2011-07-06 11 views
5

Cuando uso putStrLn txt desde varios subprocesos en Haskell, es posible obtener el texto intercalado con el final de las líneas, pero si uso putStr $ txt ++ "\n" siempre funciona.¿Por qué putStrLn fin de línea está fuera de bloqueo de hilo?

¿Es correcto? ¿Qué estoy haciendo algo mal?

Ejemplo 1:

thread 1: putStrLn "txt 1" 
thread 2: putStrLn "txt 2" 
thread 3: putStrLn "txt 3" 
thread 4: putStrLn "txt 4" 
thread 5: putStrLn "txt 5" 

Ejemplo de salida:

txt 1txt 3 
txt 2txt 5txt 4 

Ejemplo 2:

thread 1: putStr $ "txt 1" ++ "\n" 
thread 2: putStr $ "txt 2" ++ "\n" 
thread 3: putStr $ "txt 3" ++ "\n" 
thread 4: putStr $ "txt 4" ++ "\n" 
thread 5: putStr $ "txt 5" ++ "\n" 

salida siempre una línea para hilo:

txt 1 
txt 3 
txt 2 
txt 5 
txt 4 

Gracias

Actualización: estoy usando ghc 6.12.3 y base-4.2.0.2

+0

No puedo reproducir el comportamiento que describe en GHC 7.0.3 - Estoy usando forkIO y he intentado tanto en tiempo de ejecución con y sin rosca. Además, al ver la implementación de GHC en http://hackage.haskell.org/packages/archive/base/latest/doc/html/src/GHC-IO-Handle-Text.html, parece que no hay una diferencia real en la forma en que los dos casos son manejados. – Antti

+1

@Antti: Parece que se cambió en 'base 4.3.1.0'. En 'base 4.3.0.0' y anterior [se define como] (http://hackage.haskell.org/packages/archive/base/4.3.0.0/doc/html/src/System-IO.html)' putStrLn s = hacer putStr s; putChar '\ n''. – hammar

Respuesta

7

Por lo que yo puedo decir, Haskell no proporciona ninguna garantía de seguridad hilo en putStr, putStrLn y amigos, por lo que también se permitiría intercalar carácter por carácter, incluso cuando se hace la concatenación por adelantado como se hace.

Consulte Can I ensure that Haskell performs atomic IO? para ver un ejemplo de cómo sincronizar correctamente su E/S.

+0

Gracias, he estado pensando que el bloqueo se usó dentro de putStrLn. – Zhen

3

Con la definición de la base 4.3.0.0 (putStrLn s = do putStr s; putChar '\n' - Hammar gracias) Me gustaría asumir que putStr bloquea la manija stdout y por lo tanto es capaz de dar salida a la cadena sin intercalación. Eso explicaría por qué la salida se intercala al usar putStrLn: el bloqueo se libera después de putStr y otro hilo adquiere el bloqueo antes de putChar. Sin embargo, solo estoy especulando.

En cualquier caso, actualizar GHC y con ello la biblioteca base a la 4.3.1.0 debería solucionar el problema.

Cuestiones relacionadas