liveBook · Manning

Lock_guard

As explained in C++ Concurrency in Action, Second Edition

A C++ standard library class template that acquires a lock on construction and releases it on destruction.

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

How C++ Concurrency in Action, Second Edition covers it

How deep it goes
Explains construction, destruction, exception safety, lock adoption, and use with multiple mutexes.
Examples
Uses a shared list, a mutex-protected swap, and a DNS cache with exclusive updates.
What it assumes
Introduces mutex construction, lock(), and unlock() before showing scoped mutex protection.
What you can do after
Apply std::lock_guard to protect shared data and release its mutex automatically when scope ends.
How it connects
Connects mutexes and RAII with std::lock, std::adopt_lock, std::scoped_lock, and std::shared_mutex.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of C++ Concurrency in Action, Second Edition. The section links point to the parts of the book it draws on.