Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I make sure main thread ends after all other threads ends?

import Control.Concurrent
main = do
    forkIO $ putStrLn "123"
    forkIO $ putStrLn "456"

I have written the code above. But when I executed it, I always got 123 only. 456 is not printed. I guess it is because main thread ended before the other thread so the whole program just ended.

How can I prevent this? Any api can make sure main thread ended after all threads ended?

OS: OS X 10.8.3

compiler: ghc 7.4.2

like image 919
onemouth Avatar asked May 22 '13 18:05

onemouth


People also ask

How do you ensure that a thread runs after another?

To execute threads one after another it needs to be synchronized. wait notify notifyAll is useful. This is the famous interview question for the beginners, Write a program that creates 3 threads and prints alternate values in sequence.

Can you ensure all threads that started from Main must end in order in which they begin and also main should end in last?

We can use join() methodto ensure all threads that started from main must end in order in which they started and also main should end in last.In other words waits for this thread to die. Calling join() method internally calls join(0).

How will you make sure that main thread is the last one to exit?

thread. join() waits for the thread to finish before it continues. So the sub-thread will wait for each of the threads that it spawned to finish and then it will finish. The main thread will wait for the sub-thread to finish and will then finish last.

How does one ensure thread Synchronisation such that all threads wait until all threads arrive?

Barriers. Barriers are a synchronization mechanism that can be used to coordinate multiple threads working in parallel. A barrier allows each thread to wait until all cooperating threads have reached the same point, and then continue executing from there.


2 Answers

Use the async library:

import Control.Concurrent.Async

main = do
    a1 <- async $ putStrLn "123"
    a2 <- async $ putStrLn "456"
    mapM_ wait [a1, a2]

This is equivalent to Daniel's solution, except with two slight advantages:

  • It ensures that any exceptions raised in the forked threads get re-raised in the parent thread without causing a deadlock
  • It's more convenient
like image 54
Gabriella Gonzalez Avatar answered Sep 28 '22 05:09

Gabriella Gonzalez


import Control.Concurrent
main = do
    done <- newEmptyMVar
    forkIO $ putStrLn "123" >> putMVar done ()
    forkIO $ putStrLn "456" >> putMVar done ()
    takeMVar done
    takeMVar done
    -- OR: replicateM_ 2 (takeMVar done)
like image 31
Daniel Wagner Avatar answered Sep 28 '22 04:09

Daniel Wagner