[thread.mutex.requirements.mutex.general]

# 32 Concurrency support library [[thread]](./#thread)

## 32.6 Mutual exclusion [[thread.mutex]](thread.mutex#requirements.mutex.general)

### 32.6.4 Mutex requirements [[thread.mutex.requirements]](thread.mutex.requirements#mutex.general)

#### 32.6.4.2 Mutex types [[thread.mutex.requirements.mutex]](thread.mutex.requirements.mutex#general)

#### 32.6.4.2.1 General [thread.mutex.requirements.mutex.general]

[1](#1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7330)

The [*mutex types*](#def:mutex_types "32.6.4.2.1 General [thread.mutex.requirements.mutex.general]") are the standard library types mutex,recursive_mutex, timed_mutex, recursive_timed_mutex,shared_mutex, and shared_timed_mutex[.](#1.sentence-1)

They meet the requirements set out in [[thread.mutex.requirements.mutex]](thread.mutex.requirements.mutex "32.6.4.2 Mutex types")[.](#1.sentence-2)

In this description, m denotes an object of a mutex type[.](#1.sentence-3)

[*Note [1](#note-1)*:

The mutex types meet the [*Cpp17Lockable*](thread.req.lockable.req#:Cpp17Lockable "32.2.5.3 Cpp17Lockable requirements [thread.req.lockable.req]") requirements ([[thread.req.lockable.req]](thread.req.lockable.req "32.2.5.3 Cpp17Lockable requirements"))[.](#1.sentence-4)

â *end note*]

[2](#2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7340)

The mutex types meet [*Cpp17DefaultConstructible*](utility.arg.requirements#:Cpp17DefaultConstructible "16.4.4.2 Template argument requirements [utility.arg.requirements]") and [*Cpp17Destructible*](utility.arg.requirements#:Cpp17Destructible "16.4.4.2 Template argument requirements [utility.arg.requirements]")[.](#2.sentence-1)

If initialization of an object of a mutex type fails,
an exception of type system_error is thrown[.](#2.sentence-2)

The mutex types are neither copyable nor movable[.](#2.sentence-3)

[3](#3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7346)

The error conditions for error codes, if any, reported by member functions of the mutex types
are as follows:

- [(3.1)](#3.1)

  resource_unavailable_try_again â if any native handle type manipulated is not available[.](#3.1.sentence-1)

- [(3.2)](#3.2)

  operation_not_permitted â if the thread does not have the
privilege to perform the operation[.](#3.2.sentence-1)

- [(3.3)](#3.3)

  invalid_argument â if any native handle type manipulated as part of mutex
construction is incorrect[.](#3.3.sentence-1)

[4](#4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7357)

The implementation provides lock and unlock operations, as described below[.](#4.sentence-1)

For purposes of determining the existence of a data race, these behave as
atomic operations ([[intro.multithread]](intro.multithread "6.10.2 Multi-threaded executions and data races"))[.](#4.sentence-2)

The lock and unlock operations on
a single mutex appears to occur in a single total order[.](#4.sentence-3)

[*Note [2](#note-2)*:

This
can be viewed as the [modification order](intro.multithread#def:modification_order "6.10.2 Multi-threaded executions and data races [intro.multithread]") of the
mutex[.](#4.sentence-4)

â *end note*]

[*Note [3](#note-3)*:

Construction and
destruction of an object of a mutex type need not be thread-safe; other
synchronization can be used to ensure that mutex objects are initialized
and visible to other threads[.](#4.sentence-5)

â *end note*]

[5](#5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7374)

The expression m.lock() is well-formed and has the following semantics:

[6](#6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7377)

*Preconditions*: If m is of type mutex, timed_mutex,shared_mutex, or shared_timed_mutex, the calling
thread does not own the mutex[.](#6.sentence-1)

[7](#7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7383)

*Effects*: Blocks the calling thread until ownership of the mutex can be obtained for the calling thread[.](#7.sentence-1)

[8](#8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7388)

*Synchronization*: Prior unlock() operations on the same object[*synchronize with*](#def:synchronize_with) ([[intro.multithread]](intro.multithread "6.10.2 Multi-threaded executions and data races")) this operation[.](#8.sentence-1)

[9](#9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7393)

*Postconditions*: The calling thread owns the mutex[.](#9.sentence-1)

[10](#10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7397)

*Return type*: void[.](#10.sentence-1)

[11](#11)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7400)

*Throws*: system_error when
an exception is required ([[thread.req.exception]](thread.req.exception "32.2.2 Exceptions"))[.](#11.sentence-1)

[12](#12)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7405)

*Error conditions*: 

- [(12.1)](#12.1)

  operation_not_permitted â if the thread does not have the
privilege to perform the operation[.](#12.1.sentence-1)

- [(12.2)](#12.2)

  resource_deadlock_would_occur â if the implementation detects
that a deadlock would occur[.](#12.2.sentence-1)

[13](#13)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7416)

The expression m.try_lock() is well-formed and has the following semantics:

[14](#14)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7419)

*Preconditions*: If m is of type mutex, timed_mutex,shared_mutex, or shared_timed_mutex, the calling
thread does not own the mutex[.](#14.sentence-1)

[15](#15)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7425)

*Effects*: Attempts to obtain ownership of the mutex for the calling thread without
blocking[.](#15.sentence-1)

If ownership is not obtained, there is no effect and try_lock() immediately returns[.](#15.sentence-2)

An implementation may fail to obtain the lock even if it is not
held by any other thread[.](#15.sentence-3)

[*Note [4](#note-4)*:

This spurious failure is normally uncommon, but
allows interesting implementations based on a simple
compare and exchange ([[atomics]](atomics "32.5 Atomic operations"))[.](#15.sentence-4)

â *end note*]

An implementation should ensure that try_lock() does not consistently return false in the absence of contending mutex acquisitions[.](#15.sentence-5)

[16](#16)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7439)

*Synchronization*: If try_lock() returns true, prior unlock() operations
on the same object [synchronize with](intro.multithread#def:synchronize_with "6.10.2 Multi-threaded executions and data races [intro.multithread]") this operation[.](#16.sentence-1)

[*Note [5](#note-5)*:

Since lock() does not synchronize with a failed subsequenttry_lock(), the visibility rules are weak enough that little would be
known about the state after a failure, even in the absence of spurious failures[.](#16.sentence-2)

â *end note*]

[17](#17)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7449)

*Return type*: bool[.](#17.sentence-1)

[18](#18)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7452)

*Returns*: true if ownership was obtained, otherwise false[.](#18.sentence-1)

[19](#19)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7456)

*Throws*: Nothing[.](#19.sentence-1)

[20](#20)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7461)

The expression m.unlock() is well-formed and has the following semantics:

[21](#21)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7464)

*Preconditions*: The calling thread owns the mutex[.](#21.sentence-1)

[22](#22)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7468)

*Effects*: Releases the calling thread's ownership of the mutex[.](#22.sentence-1)

[23](#23)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7472)

*Return type*: void[.](#23.sentence-1)

[24](#24)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7475)

*Synchronization*: This operation [synchronizes with](intro.multithread#def:synchronize_with "6.10.2 Multi-threaded executions and data races [intro.multithread]") subsequent
lock operations that obtain ownership on the same object[.](#24.sentence-1)

[25](#25)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L7480)

*Throws*: Nothing[.](#25.sentence-1)
