liveBook · Manning

Unique_lock

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

`std::unique_lock` is a C++ standard library class template that manages ownership of a mutex lock and supports deferred locking, unlocking, and ownership transfer.

std::unique_lock manages a mutex while allowing the lock to be initially deferred, acquired or released later, and transferred to another owner. Its ownership flag lets the destructor unlock only when the object still owns the mutex. This flexibility costs additional storage and can make it slightly slower than std::lock_guard; when ownership transfer or similar flexibility is unnecessary, std::scoped_lock may be preferable if available. section 3.2.6

Listing 3.9. Using std::lock() and std::unique_lock 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::unique_lock<std::mutex> lock_a(lhs.m,std::defer_lock);   #1
        std::unique_lock<std::mutex> lock_b(rhs.m,std::defer_lock);   #1
        std::lock(lock_a,lock_b);                                     #2
        swap(lhs.some_detail,rhs.some_detail);
    }
};

The swap operation constructs two non-owning locks with std::defer_lock, then passes them to std::lock to acquire both mutexes before swapping the protected objects. section 3.2.6

A std::unique_lock can move between scopes because it is movable but not copyable. Returning a local lock transfers ownership to the caller; the caller can then continue working while the mutex remains locked. section 3.2.7

std::unique_lock<std::mutex> get_lock()
{
    extern std::mutex some_mutex;
    std::unique_lock<std::mutex> lk(some_mutex);
    prepare_data();
    return lk;                                      #1
}
void process_data()
{
    std::unique_lock<std::mutex> lk(get_lock());    #2
    do_something();
}


!@%STYLE%@!
{"css":"{\"css\": \"font-weight: bold;\"}","target":"[[{\"line\":5,\"ch\":52},{\"line\":5,\"ch\":54}],[{\"line\":9,\"ch\":52},{\"line\":9,\"ch\":54}]]"}
!@%STYLE%@!

get_lock() acquires the mutex and prepares data before returning its lock. process_data() receives ownership and calls do_something() while the data remains protected. section 3.2.7

With std::shared_mutex, std::unique_lock can provide exclusive access for updates; readers may instead use shared locks. section 3.3.2

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

How deep it goes
Explains deferred acquisition, ownership tracking, destructor behavior, move transfer, and costs without enumerating the full API.
Examples
Uses a two-mutex swap, a lock-returning data-preparation function, and exclusive updates with shared_mutex.
What you can do after
Apply deferred locking to acquire multiple mutexes safely or transfer a held lock to a caller.
How it connects
Connects mutex, std::lock, std::lock_guard, std::scoped_lock, move semantics, and shared_mutex.

Also explained in

Compare how 2 books explain unique_lock →

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.