std::shared_mutex::lock(3)
π std::shared_mutex::lock β C++ Standard Library realness
okay bestie, so this page is literally about std::shared_mutex::lock from the C++ Standard Library, and yes the name section of the original was just the name repeated twice, which is so unserious of it, but we move. π
void lock(); (since C++17)
πΈ Synopsis
So what does it do? It acquires an exclusive ownership of the shared_mutex. That's the whole vibe. β¨
But here's the important part, and I need you to actually read this one: if another thread is holding an exclusive lock or a shared lock on the same shared_mutex, then a call to lock will block execution until all such locks are released. Like, it just sits there waiting, no cap. And while shared_mutex is locked in exclusive mode, no other lock of any kind can also be held. None. Zero. The exclusivity is real. π
π¨ okay this next bit is the dangerous one, pls pay attention: iflockis called by a thread that already owns theshared_mutexin any mode (exclusive or shared), the behavior is undefined. Not "throws", not "returns an error" β undefined. main character risk fr fr. π
And one more lil technical gem: a prior unlock() operation on the same mutex synchronizes-with (as defined in std::memory_order) this operation. iykyk. π§
π«Ά Parameters
(none) β she takes no arguments, low maintenance icon.
β Return value
(none) β gives you nothing back, but honestly the exclusivity was the gift the whole time.
π Exceptions
Throws std::system_error when errors occur β including errors from the underlying operating system that would prevent lock from meeting its specifications. Rude of the OS honestly, but okay.
Good news tho: the mutex is not locked in the case of any exception being thrown. So if it throws, nothing got locked. Clean. No half-finished situationship with the mutex. π
π₯ Notes
okay so real talk: lock() is usually not called directly. Like, you can, but the cool kids use std::unique_lock, std::scoped_lock, and std::lock_guard to manage exclusive locking. That's the move. That's the whole point of those wrappers. π
π Example
okay this one's fun, run it and see:
// Run this code
#include <chrono>
#include <iostream>
#include <mutex>
#include <shared_mutex>
#include <syncstream>
#include <thread>
#include <vector>
std::mutex stream_mutx;
void print(auto const& v)
{
std::unique_lock<std::mutex> lock(stream_mutx);
std::cout << std::this_thread::get_id() << " saw: ";
for (auto e : v)
std::cout << e << ' ';
std::cout << '\n';
}
int main()
{
using namespace std::chrono_literals;
constexpr int N_READERS = 5;
constexpr int LAST = -999;
std::shared_mutex smtx;
int product = 0;
auto writer = [&smtx, &product](int start, int end)
{
for (int i = start; i < end; ++i)
{
auto data = i;
{
std::unique_lock<std::shared_mutex> lock(smtx); //
better than:
//
smtx.lock();
product = data;
}
std::this_thread::sleep_for(3ms);
}
smtx.lock(); // lock manually
product = LAST;
smtx.unlock();
};
auto reader = [&smtx, &product]
{
int data = 0;
std::vector<int> seen;
do
{
{
// better to use:
std::shared_lock lock(smtx); // smtx.lock_shared();
data = product;
} // smtx.unlock_shared();
seen.push_back(data);
std::this_thread::sleep_for(2ms);
}
while (data != LAST);
print(seen);
};
std::vector<std::thread> threads;
threads.emplace_back(writer, 1, 13);
threads.emplace_back(writer, 42, 52);
for (int i = 0; i < N_READERS; ++i)
threads.emplace_back(reader);
for (auto&& t : threads)
t.join();
}
β¨ Possible output:
127755840 saw: 43 3 3 4 46 5 6 7 7 8 9 51 10 11 11 12 -999
144541248 saw: 2 44 3 4 46 5 6 7 7 8 9 51 10 11 11 12 -999
110970432 saw: 42 2 3 45 4 5 47 6 7 8 8 9 10 11 11 12 -999
119363136 saw: 42 2 3 4 46 5 6 7 7 8 9 9 10 11 11 12 12 -999
136148544 saw: 2 44 3 4 46 5 6 48 7 8 9 51 10 11 11 12 12 -999
(notice how the reader threads each see a different lil slice of history β that's the shared/exclusive dance working π)
π See also
try_lockβ tries to lock the mutex, returns if the mutex is not available (public member function)unlockβ unlocks the mutex (public member function)lock_sharedβ locks the mutex for shared ownership, blocks if the mutex is not available (public member function)
and that's the page bestie!! sourced straight from http://cppreference.com, dated 2024.06.10, and it's literally titled std::shared_mutex::lock(3) π go forth and lock exclusively, but like, through std::unique_lock please. mwah. π
π¦ where this page comes from
- nixpkgs unstable: stdman 2024.07.05
- opensuse-leap 16.0: stdman 2024.07.05-bp160.1.9 Β· MIT
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms