main = do let steps = 10000 threads = GHC.Conc.numCapabilities counter <- atomically $ newTVar 0 ch <- newChan forM [ 1 .. threads ] $ \ t -> forkIO $ do forM [ 1 .. steps ] $ \ s -> atomically $ do c <- readTVar counter writeTVar counter (c + 1) writeChan ch () forM [ 1 .. threads ] $ \ s -> readChan ch c <- atomically $ readTVar counter putStrLn $ show c