[thread.sharedmutex.requirements.general]

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

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

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

#### 32.6.4.4 Shared mutex types [[thread.sharedmutex.requirements]](thread.sharedmutex.requirements#general)

#### 32.6.4.4.1 General [thread.sharedmutex.requirements.general]

[1](#1)

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

The standard library types shared_mutex and shared_timed_mutex are [*shared mutex types*](#def:shared_mutex_types "32.6.4.4.1 General [thread.sharedmutex.requirements.general]")[.](#1.sentence-1)

Shared mutex types meet the requirements of
mutex types ([[thread.mutex.requirements.mutex]](thread.mutex.requirements.mutex "32.6.4.2 Mutex types")) and additionally
meet the requirements set out below[.](#1.sentence-2)

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

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

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

â *end note*]

[2](#2)

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

In addition to the exclusive lock ownership mode specified
in [[thread.mutex.requirements.mutex]](thread.mutex.requirements.mutex "32.6.4.2 Mutex types"), shared mutex types provide a[*shared lock*](#def:shared_lock "32.6.4.4.1 General [thread.sharedmutex.requirements.general]") ownership mode[.](#2.sentence-1)

Multiple execution agents can
simultaneously hold a shared lock ownership of a shared mutex type[.](#2.sentence-2)

But no
execution agent holds a shared lock while another execution agent holds an
exclusive lock on the same shared mutex type, and vice-versa[.](#2.sentence-3)

The maximum
number of execution agents which can share a shared lock on a single shared
mutex type is unspecified, but is at least 10000[.](#2.sentence-4)

If more than the
maximum number of execution agents attempt to obtain a shared lock, the
excess execution agents block until the number of shared locks are
reduced below the maximum amount by other execution agents releasing their
shared lock[.](#2.sentence-5)

[3](#3)

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

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

[4](#4)

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

*Preconditions*: The calling thread has no ownership of the mutex[.](#4.sentence-1)

[5](#5)

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

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

If an exception is thrown then a shared lock has not been acquired for the current thread[.](#5.sentence-2)

[6](#6)

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

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

[7](#7)

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

*Postconditions*: The calling thread has a shared lock on the mutex[.](#7.sentence-1)

[8](#8)

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

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

[9](#9)

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

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

[10](#10)

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

*Error conditions*: 

- [(10.1)](#10.1)

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

- [(10.2)](#10.2)

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

[11](#11)

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

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

[12](#12)

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

*Preconditions*: The calling thread holds a shared lock on the mutex[.](#12.sentence-1)

[13](#13)

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

*Effects*: Releases a shared lock on the mutex held by the calling thread[.](#13.sentence-1)

[14](#14)

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

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

[15](#15)

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

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

[16](#16)

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

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

[17](#17)

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

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

[18](#18)

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

*Preconditions*: The calling thread has no ownership of the mutex[.](#18.sentence-1)

[19](#19)

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

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

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

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

[20](#20)

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

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

[21](#21)

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

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

[22](#22)

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

*Returns*: true if the shared lock was acquired, otherwise false[.](#22.sentence-1)

[23](#23)

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

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