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