Haskell Chan and MVar
An MVar and a Chan are thread-safe boxes for handing values between threads. An MVar holds at most one value, while a Chan holds a queue of values.
One worker hands one value through an MVar
A worker puts 42 into an MVar. The main thread takes it and prints it.
import Control.Concurrent (forkIO, newEmptyMVar, putMVar, takeMVar)
main :: IO ()
main = do
box <- newEmptyMVar
_ <- forkIO $ putMVar box (42 :: Int)
v <- takeMVar box
print vOne producer hands three values through a Chan in order
A producer writes 1, 2, and 3 into a Chan. The main thread reads them in order.
import Control.Concurrent (forkIO, newChan, writeChan, readChan)
main :: IO ()
main = do
ch <- newChan
_ <- forkIO $ do
writeChan ch (1 :: Int)
writeChan ch 2
writeChan ch 3
a <- readChan ch
b <- readChan ch
c <- readChan ch
print [a, b, c]Two workers hand values through two MVars in a fixed order
One worker puts 10 into the first MVar and another puts 20 into the second. The main thread takes the first, then the second.
import Control.Concurrent (forkIO, newEmptyMVar, putMVar, takeMVar)
main :: IO ()
main = do
boxA <- newEmptyMVar
boxB <- newEmptyMVar
_ <- forkIO $ putMVar boxA (10 :: Int)
_ <- forkIO $ putMVar boxB (20 :: Int)
a <- takeMVar boxA
b <- takeMVar boxB
print (a, b)Example
import Control.Concurrent (forkIO, newChan, newEmptyMVar, putMVar, readChan, takeMVar, writeChan)
main :: IO ()
main = do
ch <- newChan
result <- newEmptyMVar
_ <- forkIO $ do
writeChan ch (10 :: Int)
writeChan ch 20
writeChan ch 30
_ <- forkIO $ do
a <- readChan ch
b <- readChan ch
c <- readChan ch
putMVar result (a + b + c)
total <- takeMVar result
print totalKey points
- MVar: an MVar holds at most one value and blocks a taker until a value arrives.
- Chan: a Chan is an unbounded queue that keeps values in the order they were written.
- PutMVar: putMVar places a value into an MVar.
- TakeMVar: takeMVar takes a value from an MVar and blocks until one arrives.
- WriteChan: writeChan adds a value to the end of a Chan queue.
- ReadChan: readChan takes the oldest value from a Chan queue.
In this example, a producer thread writes 10, 20, and 30 into a Chan. A consumer thread reads all three values in order and adds them. The consumer puts the total into an MVar. The main thread takes the total and prints 60.
Note
the main thread takes results in a fixed order, so the printed order never depends on scheduling.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Haskell Playground
Exercise
What is the difference between an MVar and a Chan?