|
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Defined in header <mutex> | ||
struct defer_lock_t{explicit defer_lock_t()=default;}; | (1) | (since C++11) |
constexprstd::defer_lock_t defer_lock{}; | (2) | (since C++11) (inline since C++17) |
struct try_to_lock_t{explicit try_to_lock_t()=default;}; | (3) | (since C++11) |
constexprstd::try_to_lock_t try_to_lock{}; | (4) | (since C++11) (inline since C++17) |
struct adopt_lock_t{explicit adopt_lock_t()=default;}; | (5) | (since C++11) |
constexprstd::adopt_lock_t adopt_lock{}; | (6) | (since C++11) (inline since C++17) |
std::defer_lock_t,std::try_to_lock_t andstd::adopt_lock_t can be used in the constructor's parameter list forstd::unique_lock andstd::shared_lock to specify locking strategy.std::defer_lock,std::try_to_lock andstd::adopt_lock instances of(1,3,5) can be passed to the constructors to indicate the type of locking strategy.One of the constructors of the class templatestd::lock_guard only accepts the tagstd::adopt_lock.
| Type | Effect(s) |
defer_lock_t | do not acquire ownership of the mutex |
try_to_lock_t | try to acquire ownership of the mutex without blocking |
adopt_lock_t | assume the calling thread already has ownership of the mutex |
#include <iostream>#include <mutex>#include <thread> struct bank_account{explicit bank_account(int balance): balance{balance}{}int balance;std::mutex m;}; void transfer(bank_account& from, bank_account& to,int amount){if(&from==&to)// avoid deadlock in case of self transferreturn; // lock both mutexes without deadlockstd::lock(from.m, to.m);// make sure both already-locked mutexes are unlocked at the end of scopestd::lock_guard lock1{from.m, std::adopt_lock};std::lock_guard lock2{to.m, std::adopt_lock}; // equivalent approach:// std::unique_lock<std::mutex> lock1{from.m, std::defer_lock};// std::unique_lock<std::mutex> lock2{to.m, std::defer_lock};// std::lock(lock1, lock2); from.balance-= amount; to.balance+= amount;} int main(){ bank_account my_account{100}; bank_account your_account{50}; std::thread t1{transfer,std::ref(my_account),std::ref(your_account),10};std::thread t2{transfer,std::ref(your_account),std::ref(my_account),5}; t1.join(); t2.join(); std::cout<<"my_account.balance = "<< my_account.balance<<"\n""your_account.balance = "<< your_account.balance<<'\n';}
Output:
my_account.balance = 95your_account.balance = 55
constructs alock_guard, optionally locking the given mutex(public member function of std::lock_guard<Mutex>)[edit] | |
constructs aunique_lock, optionally locking (i.e., taking ownership of) the supplied mutex(public member function of std::unique_lock<Mutex>)[edit] |