concurrent-extra- Extra concurrency primitives

MaintainerBas van Dijk <> , Roel van Dijk <>




This module provides the Lock synchronization mechanism. It was inspired by the Python and Java Lock objects and should behave in a similar way. See:


All functions are exception safe. Throwing asynchronous exceptions will not compromise the internal state of a Lock.

This module is intended to be imported qualified. We suggest importing it like:

 import           Control.Concurrent.Lock         ( Lock )
 import qualified Control.Concurrent.Lock as Lock ( ... )



data Lock Source

A lock is in one of two states, "locked" or "unlocked".


Creating locks

new :: IO LockSource

Create an unlocked lock.

newAcquired :: IO LockSource

Create a locked lock.

Locking and unlocking

acquire :: Lock -> IO ()Source

When the state is unlocked, acquire changes the state to locked and returns immediately. When the state is locked, acquire blocks until a call to release in another thread changes it to unlocked, then the acquire call resets it to locked and returns.

There are two further important properties of acquire:

  • acquire is single-wakeup. That is, if there are multiple threads blocked on acquire, and the lock is released, only one thread will be woken up. The runtime guarantees that the woken thread completes its acquire operation.
  • When multiple threads are blocked on acquire, they are woken up in FIFO order. This is useful for providing fairness properties of abstractions built using locks. (Note that this differs from the Python implementation where the wake-up order is undefined)

tryAcquire :: Lock -> IO BoolSource

A non-blocking acquire. When the state is unlocked, tryAcquire changes the state to locked and returns immediately with True. When the state is locked, tryAcquire leaves the state unchanged and returns immediately with False.

release :: Lock -> IO ()Source

release changes the state to unlocked and returns immediately.

Note that it is an error to release an unlocked lock!

If there are any threads blocked on acquire the thread that first called acquire will be woken up.

Convenience functions

with :: Lock -> IO a -> IO aSource

A convenience function which first acquires the lock and then performs the computation. When the computation terminates, whether normally or by raising an exception, the lock is released.

Note that: with = liftA2 bracket_ acquire release.

tryWith :: Lock -> IO α -> IO (Maybe α)Source

A non-blocking with. tryWith is a convenience function which first tries to acquire the lock. If that fails, Nothing is returned. If it succeeds, the computation is performed. When the computation terminates, whether normally or by raising an exception, the lock is released and Just the result of the computation is returned.

Querying locks

locked :: Lock -> IO BoolSource

Determines if the lock is in the locked state.

Notice that this is only a snapshot of the state. By the time a program reacts on its result it may already be out of date.