std::lock_guard is a C++ standard library class template that locks a supplied mutex when constructed and unlocks it when destroyed. This RAII pattern prevents missed unlocks on normal returns and exception paths. section 3.2.1
Listing 3.1. Protecting a list with a mutex
#include <list>
#include <mutex>
#include <algorithm>
std::list<int> some_list; #1
std::mutex some_mutex; #2
void add_to_list(int new_value)
{
std::lock_guard<std::mutex> guard(some_mutex); #3
some_list.push_back(new_value);
}
bool list_contains(int value_to_find)
{
std::lock_guard<std::mutex> guard(some_mutex); #4
return std::find(some_list.begin(),some_list.end(),value_to_find)
!= some_list.end();
}
!@%STYLE%@!
{"css":"{\"css\": \"font-weight: bold;\"}","target":"[[{\"line\":3,\"ch\":53},{\"line\":3,\"ch\":55}],[{\"line\":4,\"ch\":53},{\"line\":4,\"ch\":55}],[{\"line\":7,\"ch\":53},{\"line\":7,\"ch\":55}],[{\"line\":12,\"ch\":53},{\"line\":12,\"ch\":55}]]"}
!@%STYLE%@!
The list operations each hold the same mutex for their duration, so readers cannot observe a partially modified list. section 3.2.1
For multiple mutexes, std::lock can acquire them first; guards constructed with std::adopt_lock then take ownership and release them on exit. C++17 std::scoped_lock provides a variadic alternative. section 3.2.4 section 3.2.4
Listing 3.6. Using std::lock() and std::lock_guard in a swap operation
class some_big_object;
void swap(some_big_object& lhs,some_big_object& rhs);
class X
{
private:
some_big_object some_detail;
std::mutex m;
public:
X(some_big_object const& sd):some_detail(sd){}
friend void swap(X& lhs, X& rhs)
{
if(&lhs==&rhs)
return;
std::lock(lhs.m,rhs.m); #1
std::lock_guard<std::mutex> lock_a(lhs.m,std::adopt_lock); #2
std::lock_guard<std::mutex> lock_b(rhs.m,std::adopt_lock); #3
swap(lhs.some_detail,rhs.some_detail);
}
};
!@%STYLE%@!
{"css":"{\"css\": \"font-weight: bold;\"}","target":"[[{\"line\":13,\"ch\":68},{\"line\":13,\"ch\":70}],[{\"line\":14,\"ch\":68},{\"line\":14,\"ch\":70}],[{\"line\":15,\"ch\":68},{\"line\":15,\"ch\":70}]]"}
!@%STYLE%@!
The swap operation uses std::lock followed by two guards, illustrating ownership of already-acquired locks. section 3.2.4
With std::shared_mutex, std::lock_guard provides exclusive access for updates; read-only operations can instead use std::shared_lock for shared access. section 3.3.2
