As a former C++ programmer, the behaviour of Haskell threads is confusing. Refer to the following Haskell code snippet:
import Control.Concurrent
import Control.Concurrent.MVar
import Data.Functor.Compose
import System.Random
randomTill0 :: MVar () -> IO () -- Roll a die until 0 comes
randomTill0 mV = do
x <- randomRIO (0,65535) :: IO Int
if 0 == x
then putMVar mV ()
else randomTill0 mV
main :: IO ()
main = do
n <- getNumCapabilities
mV <- newEmptyMVar
sequence (replicate n (forkIO (randomTill0 mV)))
readMVar mV
putStrLn "Excution complete."
As far as I know, Haskell's forkIO
is roughly equivalent to C++'s std::async
. In C++, I store a std::future
which is returned by std::async
, then std::future::wait
for it, then the thread will be std::thread::join
ed.
(Regarding the tiny delay before the message, I don't think any laziness is involved here.)
My question is:
In the above Haskell code snippet, when are the threads resulting from forkIO
s joined? Is it upon readMVar mV
, or the end of main
?
Is there a Haskell equivalent of std::thread::detach
?
As far as I understand, threads are never joined, and the program ends when main
ends. This is special to main
–– in general threads are not associated to each other in any kind of hierarchy. The concept of joining a thread does not exist: a thread runs until its action is finished or until it is explicitly killed with killThread
, and then it evaporates (thanks, garbage collector). If you want to wait for a thread to complete you have to do it yourself, probably with an MVar
.
It follows that there is no analogue of detach
–– all threads are automatically detached.
Another thing worth mentioning is that there is not a 1:1 correspondence between OS threads and Haskell threads. The Haskell runtime system has its own scheduler that can run multiple Haskell threads on a single OS thread; and in general a Haskell thread will bounce around between different OS threads over the course of its lifetime. There is a concept of bound threads which are tied to an OS thread, but really the only reason to use that is if you are interfacing with code in other languages that distinguishes between OS threads.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With