Why would I want to lock two mutexes in one function - that too with deferred lock?

unique_lock
mutex lock
mutex functions
std::lock
unique_lock vs scoped_lock
c++ mutex
lock_guard recursive_mutex
std::lock_guard

https://en.cppreference.com/w/cpp/thread/lock_tag

void transfer(bank_account &from, bank_account &to, int amount)
{
    // lock both mutexes without deadlock
    std::lock(from.m, to.m);
    // make sure both already-locked mutexes are unlocked at the end of scope
    std::lock_guard<std::mutex> lock1(from.m, std::adopt_lock);
    std::lock_guard<std::mutex> 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;
}

What do they gain by locking two mutexes at once? What have they gained by defered lock here?

Please explain the reason behind that decision of theirs.


Extension on Richard Hodges's answer

What do they gain by locking two mutexes at once?

Richard explained nicely already, just a little bit more explicit: we avoid dead-lock this way (std::lock is implemented such that dead-lock won't occur).

What have they gained by deferred lock here?

Deferring the lock results in not acquiring it immediately. That's important because if they did so, they would just do it without any protection against dead-lock (which the subsequent std::lock then achieves).

About dead lock avoidance (see std::lock):

Locks the given Lockable objects lock1, lock2, ..., lockn using a deadlock avoidance algorithm to avoid deadlock.

The objects are locked by an unspecified series of calls to lock, try_lock, and unlock. [...]

Side note: another, much simpler algorithm avoiding dead locks is always locking the bank account with e. g. lower account number (AN) first. If a thread is waiting for the lock of higher AN, then the other thread holding it either already has both of the locks acquired or is waiting for the second – which cannot be the one of the first thread as it must have a yet higher AN.

This does not change much for arbitrary number of threads, any thread holding a lower lock is waiting for a higher one, if hold as well. If you draw a directed graph with edges from A to B if A is waiting for second lock that B holds, you'll get a (multi-) tree structure, but you won't ever have circular substructures (which would indicate a dead lock).

Prefer Locks to Mutexes, Since there are many possible mutex and lock types that an application The simplest implementation for 3 mutexes looks like this: This code is very long-​winded, with all the duplication between the case blocks. The lock_helper function locks the first mutex, and then tries to lock the other two in turn. When transferring money from one account to another, we need to lock both accounts (since we are removing money from one and adding it to another). We would like this operation not to deadlock, so lock both at once using std::lock , since doing it like that ensures there isn't a deadlock.


If I modify a bank account without locking it, someone else could try to modify it at the same time. This is a race and the result will be undefined behaviour (usually lost or magically created money).

While transferring money, I am modifying 2 bank accounts. So they both need to be locked.

The problem is that when locking more than one thing, every locker must lock and unlock in the same order, otherwise we get deadlocks.

When it's bank accounts, there is no natural order of locks. Thousands of threads could be transferring money in all directions.

So we need a method of locking more than one mutex in a way that works around this - this is std::lock

std::lock merely locks the mutex - it does not guarantee unlocking on exit from the current code block.

std::lock_guard<> unlocks the mutex it's referring to upon destruction (see RAII). This makes the code behave correctly in all circumstances - even when there is an exception which might cause an early exit from the current code block without the code flowing over statement such as to.m.unlock()

A good explanation (with examples) here: https://wiki.sei.cmu.edu/confluence/display/cplusplus/CON53-CPP.+Avoid+deadlock+by+locking+in+a+predefined+order

Acquiring Multiple Locks Without Deadlock, because we want a fast mutex operation, and page table manipulations are (If we are using the multiple memory model, then all is well, since we can perform the address space change, as in this case it is very fast.) Lock the kernel 2. or kill the first one – in this case it would delay the function to be performed, and keep  int pthread_mutex_lock (pthread_mutex_t *mutex) : Locks a mutex object, which identifies a mutex. If the mutex is already locked by another thread, the thread waits for the mutex to become available. The thread that has locked a mutex becomes its current owner and remains the owner until the same thread has unlocked it. When the mutex has the


The bank account data structure has a lock for each account.

When transferring money from one account to another, we need to lock both accounts (since we are removing money from one and adding it to another). We would like this operation not to deadlock, so lock both at once using std::lock, since doing it like that ensures there isn't a deadlock.

After we finish the transaction we need to make sure we release the lock. This code does that using RAII. With the adopt_lock tag, we make the object adopt an already locked mutex (which will be released when lock1 falls out of scope). With the defer_lock tag, we create a unique_lock for a currently unlocked mutex, with the intention of locking it later. Again, it will be unlocked when the unique_lock falls out of scope.

Symbian OS Internals: Real-time Kernel Programming, One of the biggest problems (read nightmares!) in developing the new runtime was placed some limits on who could take such actions, they were still very much present. The next issue was the selection of the cancellation mode - deferred have been interrupted whilst holding one of the locks to access a global table. Yes! In fact it's common to have one lock per data structure that you need to update. If you only have one lock, then they may be significant contention for the lock between two threads that was unnecessary. For example if two threads were updating two different counters, it might not be necessary to use the same lock.


from and to are 2 accounts which may be used anywhere in the application separatelly.

By having mutex for each account, you make sure nobody uses from nor to accounts while you do the transfer.

lock_guard will release mutex when exiting from function.

AUUGN, The benefit to using std::unique_lock<> comes from two things: object does not have to own the lock on the mutex it is associated with. Transferring ownership of a mutex lock between std::unique_lock<> instances For example, you can write a simple function that acquires a lock on an internal mutex: First, the concept should be clear from the earlier tutorial i.e. WHY you need a lock? If that is answered, it can be assumed that you have a critical section (CS) which is a piece of code that can be executed simultaneously by multiple threads and is modifying at least one shared variable and at least two threads.


Multithreading in C++0x part 5: Flexible locking with std , If this were to happen, then the thread would attempt to acquire the lock and spin Consequently, an I0SimpleLock should only be acquired for very brief as allocating memory or acquiring a mutex, since this could result in a deadlock. ever have to handle an interrupt directly and, if they do, most will defer the interrupt to  A mutex is used to permit only one thread at a time to have exclusive access to some resource, which is typically some variable or data structure. Mutexes are so common that many words have been coined to describe their operation. Each Lock mu has two basic operations: mu.Acquire() and mu.Release().


OS X and iOS Kernel Programming, The use of a binary semaphore as a flag or as an integer variable Mutex to a resource ( a section of the codes or critical section codes or a function ) . It works as a resource locking mechanism if the access to certain resources is blocked . a critical section is too long compared to the time that an ISR would have taken . To keep an area of a worksheet visible while you scroll to another area of the worksheet, go to the View tab, where you can Freeze Panes to lock specific rows and columns in place, or you can Split panes to create separate windows of the same worksheet. Skip ahead to live broadcast. LIVE. Freeze rows or columns. Freeze the first column.


Embedded systems: architecture, programming and design, If one thread has locked a mutex, then another thread attempting to lock that same to acquire multiple mutexes at the same time to perform a multi-object access, but A function A that uses mutexes does not necessarily compose nicely with a want to defer asynchronous interrupt processing while you hold the mutex,  Then, the call to std::lock() (#1) locks the two mutexes, and two std::lock_guard instances are constructed (#2, #3): one for each mutex. The std::adopt_lock parameter is supplied in addition to the mutex to indicate to the std::lock_guard objects that the mutexes are already locked, and they should just "adopt" the lock on the mutex rather