std::unique_lock
<mutex>
class unique_lock;
The class unique_lock
is a general-purpose mutex ownership wrapper allowing deferred locking, time-constrained attempts at locking, recursive locking, transfer of lock ownership, and use with condition variables.
The class unique_lock
is movable, but not copyable -- it meets the requirements of MoveConstructible and MoveAssignable but not of CopyConstructible or CopyAssignable.
The class unique_lock
meets the BasicLockable requirements. If Mutex
meets the Lockable requirements, unique_lock
also meets the Lockable requirements (ex.: can be used in std::lock ); if Mutex
meets the TimedLockable requirements, unique_lock
also meets the TimedLockable requirements.
Contents
[edit] Template parameters
[edit] Nested types
mutex_type
Mutex
[edit] Member functions
unique_lock
, optionally locking (i.e., taking ownership of) the supplied mutex (public member function) [edit]
(public member function) [edit]
(public member function) [edit]
Locking
(public member function) [edit]
(public member function) [edit]
(public member function) [edit]
Modifiers
(public member function) [edit]
Observers
[edit] Non-member functions
[edit] Notes
A common beginner error is to "forget" to give a unique_lock
variable a name, e.g. std::unique_lock(mtx); (which default constructs a unique_lock
variable named mtx
) or std::unique_lock{mtx}; (which constructs a prvalue object that is immediately destroyed), thereby not actually constructing a lock that holds a mutex for the rest of the scope.
[edit] Example
#include <iostream> #include <mutex> #include <thread> struct Box { explicit Box(int num) : num_things{num} {} int num_things; std::mutex m; }; void transfer(Box& from, Box& to, int num) { // don't actually take the locks yet std::unique_lock lock1{from.m, std::defer_lock }; std::unique_lock lock2{to.m, std::defer_lock }; // lock both unique_locks without deadlock std::lock (lock1, lock2); from.num_things -= num; to.num_things += num; // "from.m" and "to.m" mutexes unlocked in unique_lock dtors } int main() { Box acc1{100}; Box acc2{50}; std::thread t1{transfer, std::ref (acc1), std::ref (acc2), 10}; std::thread t2{transfer, std::ref (acc2), std::ref (acc1), 5}; t1.join(); t2.join(); std::cout << "acc1: " << acc1.num_things << "\n" "acc2: " << acc2.num_things << '\n'; }
Output:
acc1: 95 acc2: 55
[edit] Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
LWG 2981 | C++17 | redundant deduction guide from unique_lock<Mutex> was provided
|
removed |