Channel Synchronization in Haskell

In Haskell, we can use MVars for synchronization across threads. Here’s an example of using a blocking receive to wait for a thread to finish. When waiting for multiple threads to finish, you may prefer to use a similar mechanism to WaitGroup, which can be implemented using MVars.

import Control.Concurrent (forkIO, threadDelay, MVar, newEmptyMVar, putMVar, takeMVar)
import System.IO (hFlush, stdout)

-- This is the function we'll run in a separate thread. The
-- `done` MVar will be used to notify the main thread that 
-- this function's work is done.
worker :: MVar Bool -> IO ()
worker done = do
    putStr "working..."
    hFlush stdout
    threadDelay 1000000  -- Sleep for 1 second
    putStrLn "done"
    -- Send a value to notify that we're done.
    putMVar done True

main :: IO ()
main = do
    -- Create an empty MVar to use for synchronization
    done <- newEmptyMVar
    
    -- Start a worker thread, giving it the MVar to notify on.
    forkIO $ worker done
    
    -- Block until we receive a notification from the
    -- worker on the MVar.
    takeMVar done

To run the program:

$ runhaskell channel-synchronization.hs
working...done

If you removed the takeMVar done line from this program, the program would exit before the worker even started.

In this Haskell version:

  1. We use MVar instead of channels for synchronization.
  2. The forkIO function is used to start a new thread, similar to goroutines in Go.
  3. threadDelay is used to simulate work, similar to time.Sleep in Go.
  4. putMVar is used to send a signal, similar to sending on a channel in Go.
  5. takeMVar is used to wait for the signal, similar to receiving from a channel in Go.

This example demonstrates how to use MVars in Haskell for basic thread synchronization, which is conceptually similar to using channels for goroutine synchronization in Go.

查看推荐产品

Comments powered by Disqus