Multithreading 尝试创建多个线程时程序崩溃

Multithreading 尝试创建多个线程时程序崩溃,multithreading,haskell,concurrency,Multithreading,Haskell,Concurrency,我有以下计划: module Main where import System (getArgs) import Control.Concurrent import Control.Monad spawn left id = do right <- newEmptyMVar forkIO (thread id left right) return right thread id left right = go where go = do l <- t

我有以下计划:

module Main where

import System (getArgs)
import Control.Concurrent
import Control.Monad

spawn left id = do
   right <- newEmptyMVar
   forkIO (thread id left right) 
   return right

thread id left right = go 
   where go = do l <- takeMVar left
                 putStrLn (show id)
                 putMVar right ()

main = do
   args <- getArgs
   if null args then
      putStrLn "Arguments not supplied"
   else do
      initial <- newEmptyMVar
      final <- foldM spawn initial [1..(read (head args))]
      putMVar initial ()
      takeMVar final
modulemain其中
导入系统(getArgs)
导入控制。并发
进口管制
产卵左id=do

右创建的每个线程都需要自己的程序堆栈。我不知道Haskell在线程中使用了多大的堆栈,但是如果它是4KB(实际上非常小),那么对于一百万个堆栈来说,它将是4GB。如果你在一台32位的机器上,那就是所有的可寻址内存,所以这显然是行不通的。典型的堆栈大小更像一个兆字节

根据,每个线程的初始堆栈大小默认为1K,并且可以根据需要增加到每线程8M

您可以使用RTS选项
-k
-k
调整这些数字,例如:

$ ./Threads 1000000 +RTS -k512 -K1K -s
您的程序在我的系统上运行良好(64位,6GB RAM),但在峰值时消耗的内存确实超过2GB

   4,743,629,168 bytes allocated in the heap
   4,368,720,328 bytes copied during GC
   1,043,256,808 bytes maximum residency (11 sample(s))
     221,352,512 bytes maximum slop
            2413 MB total memory in use (0 MB lost due to fragmentation)

  Generation 0:  8707 collections,     0 parallel,  1.46s,  1.59s elapsed
  Generation 1:    11 collections,     0 parallel,  1.72s,  3.16s elapsed

  INIT  time    0.00s  (  0.00s elapsed)
  MUT   time    5.86s  ( 15.76s elapsed)
  GC    time    3.18s  (  4.75s elapsed)
  EXIT  time    0.08s  (  0.08s elapsed)
  Total time    9.12s  ( 20.59s elapsed)

  %GC time      34.9%  (23.1% elapsed)

  Alloc rate    798,590,769 bytes per MUT second

  Productivity  65.1% of total user, 28.9% of total elapsed

./Threads 1000000 +RTS -K1K -s  9.12s user 3.92s system 62% cpu 20.815 total

显然,我被我以前的一个程序启动了一百万个线程,但运行良好这一事实愚弄了。现在我意识到,由于这些线程没有互相等待,在创建新线程时,其中一些线程已经结束。因此,即使它的内存不足,SIGKILL也是错误的错误消息。应该说是内存不足。你应该提交一份bug报告。@augustss你可以从linux内存不足杀手那里得到一个SIGKILL,不是吗?运行时真的(按设计)没有办法处理这个问题。@sclv我不能相信一个程序不能保护自己,所以不会收到SIGKILL。当然,在某些情况下,信号将被发送,但ghc rts应确保信号不会发生。我称之为bug。@augustss:“与SIGTERM和SIGINT相比,这个信号不能被捕获或忽略,接收过程在接收到这个信号时不能执行任何清理。”