Next: Semaphores, Previous: Special Variables, Up: Threading

### 12.3 Mutex Support

Mutexes are used for controlling access to a shared resource. One thread is allowed to hold the mutex, others which attempt to take it will be made to wait until it's free. Threads are woken in the order that they go to sleep.

There isn't a timeout on mutex acquisition, but the usual WITH-TIMEOUT macro (which throws a TIMEOUT condition after n seconds) can be used if you want a bounded wait.

         (defpackage :demo (:use "CL" "SB-THREAD" "SB-EXT"))

         (in-package :demo)

         (defvar *a-mutex* (make-mutex :name "my lock"))

         (defun thread-fn ()
           (format t "Thread ~A running ~%" *current-thread*)
           (with-mutex (*a-mutex*)
             (format t "Thread ~A got the lock~%" *current-thread*)
             (sleep (random 5)))
           (format t "Thread ~A dropped lock, dying now~%" *current-thread*))

         (make-thread #'thread-fn)
         (make-thread #'thread-fn)

— Structure: sb-thread:mutex

> Class precedence list: `mutex, structure-object, t`

> Mutex type.

— Function: sb-thread:make-mutex &key name %owner

> Create a mutex.

— Function: sb-thread:mutex-name instance

> Name of a `queue`. Can be assingned to using `setf`. Queue names can be arbitrary printable objects, and need not be unique.

— Function: sb-thread:mutex-value mutex

> Current owner of the mutex, `nil` if the mutex is free. May return a stale value, use `mutex-owner` instead.

— Function: sb-thread:get-mutex mutex &optional new-owner waitp

> Acquire `mutex` for `new-owner`, which must be a thread or `nil`. If `new-owner` is `nil`, it defaults to the current thread. If `waitp` is non-NIL and the mutex is in use, sleep until it is available.

> Note: using `get-mutex` to assign a `mutex` to another thread then the current one is not recommended, and liable to be deprecated.

> `get-mutex` is not interrupt safe. The correct way to call it is:

>                (WITHOUT-INTERRUPTS
>                  ...
>                  (ALLOW-WITH-INTERRUPTS (GET-MUTEX ...))
>                  ...)

> `without-interrupts` is necessary to avoid an interrupt unwinding the call while the mutex is in an inconsistent state while `allow-with-interrupts` allows the call to be interrupted from sleep.

> It is recommended that you use `with-mutex` instead of calling `get-mutex` directly.

— Function: sb-thread:release-mutex mutex &key if-not-owner

> Release `mutex` by setting it to `nil`. Wake up threads waiting for this mutex.

> `release-mutex` is not interrupt safe: interrupts should be disabled around calls to it.

> If the current thread is not the owner of the mutex then it silently returns without doing anything (if `if-not-owner` is :PUNT), signals a `warning` (if `if-not-owner` is :WARN), or releases the mutex anyway (if `if-not-owner` is :FORCE).

— Macro: sb-thread:with-mutex (mutex &key value wait-p) &body body

> Acquire `mutex` for the dynamic scope of `body`, setting it to `new-value` or some suitable default value if `nil`. If `wait-p` is non-NIL and the mutex is in use, sleep until it is available

— Macro: sb-thread:with-recursive-lock (mutex) &body body

> Acquires `mutex` for the dynamic scope of `body`. Within that scope further recursive lock attempts for the same mutex succeed. It is allowed to mix `with-mutex` and `with-recursive-lock` for the same mutex provided the default value is used for the mutex.