【发布时间】:2013-10-13 17:07:16
【问题描述】:
我有以下代码:
module Main where
import Data.IORef
import qualified Data.ByteString as S
import Control.Monad
import Control.Concurrent
main :: IO ()
main = do
var <- newIORef False
forkIO $ forever $ do
status <- readIORef var
if status
then putStrLn "main: file was read"
else putStrLn "main: file not yet read"
threadDelay 10000
threadDelay 200000
putStrLn ">>! going to read file"
--threadDelay 200000 --
str <- S.readFile "large2"
putStrLn ">>! finished reading file"
writeIORef var True
threadDelay 200000
我编译代码并像这样运行它:
$ ghc -threaded --make test.hs
$ dd if=/dev/urandom of=large bs=800000 count=1024
$ ./test +RTS -N3
<...>
main: file not yet read
main: file not yet read
main: file not yet read
main: file not yet read
>>! going to read file
>>! finished reading file
main: file was read
main: file was read
main: file was read
main: file was read
<...>
即程序在读取文件时暂停。我觉得这很混乱,因为如果我用threadDelay 替换readFile,它会正确地产生控制。
这里发生了什么? GHC 不是将forkIO'd 代码映射到不同的系统线程吗?
(我使用的是 Mac OS X 10.8.5,但人们报告了在 Ubuntu 和 Debian 上的相同行为)
【问题讨论】:
-
惰性 IO。它实际上并不是在读取文件,而是立即打印这两行。
-
swish:这里不是这样。这是严格的 IO。它是 Data.Bytestring.readFile。运行程序时有明显的停顿。
-
似乎 RTS 调度程序在一个绑定线程中运行这些绿色线程。只是好奇:forkOS 呢?
-
alvelcom:forkOS 创建的绑定线程并不能保证创建一个新的操作系统线程,只是为了始终在同一个操作系统线程中始终运行安全调用。您不一定要使用 forkOS 来声明专用的 OS 线程。
-
在某些运行中,我得到了与 OP 相同的行为,但是大约 50% 的时间程序的行为符合预期。这里似乎发生了一些有趣的事情。
标签: multithreading haskell concurrency