Acquire a lock on two mutexes and avoid deadlock - c++

The following code contains a potential deadlock, but seems to be necessary: to safely copy data to one container from another, both containers must be locked to prevent changes from occurring in another thread.
void foo::copy(const foo & rhs)
{
pMutex->lock();
rhs.pMutex->lock();
// do copy
}
Foo has an STL container and "do copy" essentially consists of using std::copy. How do I lock both mutexes without introducing deadlock?

Impose some kind of total order on instances of foo and always acquire their locks in either increasing or decreasing order, e.g., foo1->lock() and then foo2->lock().
Another approach is to use functional semantics and instead write a foo::clone method that creates a new instance rather than clobbering an existing one.
If your code is doing lots of locking, you may need a complex deadlock-avoidance algorithm such as the banker's algorithm.

How about this?
void foo::copy(const foo & rhs)
{
scopedLock lock(rhs.pMutex); // release mutex in destructor
foo tmp(rhs);
swap(tmp); // no throw swap locked internally
}
This is exception safe, and pretty thread safe as well. To be 100% thread save you'll need to review all code path and than re-review again with another set of eyes, after that review it again...

As #Mellester mentioned you can use std::lock for locking multiple mutexes avoiding deadlock.
#include <mutex>
void foo::copy(const foo& rhs)
{
std::lock(pMutex, rhs.pMutex);
std::lock_guard<std::mutex> l1(pMutex, std::adopt_lock);
std::lock_guard<std::mutex> l2(rhs.pMutex, std::adopt_lock);
// do copy
}
But note to check that rhs is not a *this since in this case std::lock will lead to UB due to locking same mutex.

this is a known problem already there is a std solution.
std::lock() can be called on 2 or more mutex at the same time whilst avoiding deadlock's.
More information here
it does offer a recommendation.
std::scoped_lock offers a RAII wrapper for this function, and is
generally preferred to a naked call to std::lock.
of course this doesn't really allow early releases of one lock above the other so use std::defer_lock or std::adopt_lock like I did in this answer to a similar question.

To avoid a deadlock its probably best, to wait until both resources can be locked:
Dont know which mutex API you are using so here is some arbitrary pseudo code, assume that can_lock() only checks if it can lock a mutex, and that try_lock() returns true if it did lock, and false, if the mutex is already locked by somebody else.
void foo::copy(const foo & rhs)
{
for(;;)
{
if(! pMutex->cany_lock() || ! rhs.pMutex->cany_lock())
{
// Depending on your environment call or dont call sleep()
continue;
}
if(! pMutex->try_lock())
continue;
if(! rhs.pMutex->try_lock())
{
pMutex->try_lock()
continue;
}
break;
}
// do copy
}

You can try locking both the mutexes at the same time using scoped_lock or auto_lock.... like bank transfer do...
void Transfer(Receiver recv, Sender send)
{
scoped_lock rlock(recv.mutex);
scoper_lock slock(send.mutex);
//do transaction.
}

Related

Is using unique_lock in new scope equivalent to unlock call at the end of work with shared resource?

I have seen a lot of examples of code when developer uses std::unique_lock in new scope for automatically unlocking mutex:
...
// do some staff
{
std::unique_lock<std::mutex> lock(shared_resource_mutex);
// do some actions with shared resource
}
// do some staff
...
In my opinion it would be better to implement this behaviour using method unlock from std::unique_lock API in this way:
...
// do some actions
std::unique_lock<std::mutex> lock(shared_resource_mutex);
// do some actions with shared resource
lock.unlock();
// do some actions
...
Are these two fragments of code equivalent? For what purpose developers use the first variant? Maybe to emphasize (using parentheses) code that can not be executed parallel?
When the object is destroyed at the end of the scope, the lock is released. That's the whole point of RAII.
The good thing about using RAII is that you cannot forget to unlock and it doesn't matter how you leave the scope. If an exception is thrown for example, the lock will still be released.
If all you need is lock at construction and unlock at destruction, then std::scoped_lock is an even simpler/more appropriate class to use though.
I would say the former method is safer, more consistent and easier to read.
First consider safety:
void function()
{
std::unique_lock<std::shared_mutex> lock(mtx);
// exclusive lock stuff
lock.unlock();
// std::shared_lock<std::shared_mutex> lock(mtx); // whoops name in use
std::shared_lock<std::shared_mutex> lock2(mtx);
// read only shared lock stuff here
lock2.unlock(); // what if I forget to do this?
lock.lock(); // if I forgot to call lock2.unlock() undefined behavior
// back to the exclusive stuff
lock.unlock();
}
If you have different locks to acquire/release and you forget to call unlock() then you may end up trying to lock the same mutex twice from the same thread.
That is undefined behavior so it may go unnoticed but cause trouble.
And what if you call either lock() or unlock() on the wrong lock variable.... (say on lock2 rather than lock1?) the possibilities are frightening.
Consistency:
Also, not all lock types have a .unlock() function (std::scoped_lock, std::lock_guard) so it is good to be consistent with your coding style.
Easier to read:
It is also easier to see what code sections use locks which makes reasoning on the code simpler:
void function()
{
{
std::unique_lock<std::shared_mutex> lock(mtx);
// exclusive lock stuff
}
{
std::shared_lock<std::shared_mutex> lock(mtx);
// read only shared lock stuff here
}
{
std::unique_lock<std::shared_mutex> lock(mtx);
// back to the exclusive stuff
}
}
Both of your approaches are correct, and you might choose either of them depending on circumstance. For example, when using a condition_variable/lock combination it's often useful to be able to explicitly lock and unlock the lock.
Here's another approach that I find to be both expressive and safe:
#include <mutex>
template<class Mutex, class Function>
decltype(auto) with_lock(Mutex& m, Function&& f)
{
std::lock_guard<Mutex> lock(m);
return f();
}
std::mutex shared_resource_mutex;
void something()
{
with_lock(shared_resource_mutex, [&]
{
// some actions
});
// some other actions
}

Locking pairs of mutually referencing resources

Consider the following:
// There are guys:
class Guy {
// Each guy can have a buddy:
Guy* buddy; // When a guy has a buddy, he is his buddy's buddy, i.e:
// assert(!buddy || buddy->buddy == this);
public:
// When guys are birthed into the world they have no buddy:
Guy()
: buddy{}
{}
// But guys can befriend each other:
friend void befriend(Guy& a, Guy& b) {
// Except themselves:
assert(&a != &b);
// Their old buddies (if any), lose their buddies:
if (a.buddy) { a.buddy->buddy = {}; }
if (b.buddy) { b.buddy->buddy = {}; }
a.buddy = &b;
b.buddy = &a;
}
// When a guy moves around, he keeps track of his buddy
// and lets his buddy keep track of him:
friend void swap(Guy& a, Guy& b) {
std::swap(a.buddy, b.buddy);
if (a.buddy) { a.buddy->buddy = &a; }
if (b.buddy) { b.buddy->buddy = &b; }
}
Guy(Guy&& guy)
: Guy()
{
swap(*this, guy);
}
Guy& operator=(Guy guy) {
swap(*this, guy);
return *this;
}
// When a Guy dies, his buddy loses his buddy.
~Guy() {
if (buddy) { buddy->buddy = {}; }
}
};
All is well so far, but now I want this to work when buddies are used in different threads. No problem, let's just stick std::mutex in Guy:
class Guy {
std::mutex mutex;
// same as above...
};
Now I just have to lock mutexes of both guys before linking or unlinking the pair of them.
This is where I am stumped. Here are failed attempts (using the destructor as an example):
Deadlock:
~Guy() {
std::unique_lock<std::mutex> lock{mutex};
if (buddy) {
std::unique_lock<std::mutex> buddyLock{buddy->mutex};
buddy->buddy = {};
}
}
When two buddies are destroyed at around the same time, it is possible that each of them locks their own mutex, before trying to lock their buddies' mutexes, thus resulting in a deadlock.
Race condition:
Okay so we just have to lock mutexes in consistent order, either manually or with std::lock:
~Guy() {
std::unique_lock<std::mutex> lock{mutex, std::defer_lock};
if (buddy) {
std::unique_lock<std::mutex> buddyLock{buddy->mutex, std::defer_lock};
std::lock(lock, buddyLock);
buddy->buddy = {};
}
}
Unfortunately, to get to buddy's mutex we have to access buddy which at this point is not protected by any lock and may be in the process of being modified from another thread, which is a race condition.
Not scalable:
Correctness can be attained with a global mutex:
static std::mutex mutex;
~Guy() {
std::unique_lock<std::mutex> lock{mutex};
if (buddy) { buddy->buddy = {}; }
}
But this is undesirable for performance and scalability reasons.
So is this possible to do without global lock? How?
Using std::lock isn't a race condition (per se) nor does it risk deadlock.
std::lock will use a deadlock-free algorithm to obtain the two locks. They will be some kind of (unspecified) try-and-retreat method.
An alternative is to determine an arbitrary lock order for example using the physical address of the objects.
You've correctly excluded the possibility that an objects buddy is itself so there's no risk of trying to lock() the same mutex twice.
I say isn't a race condition per se because what that code will do is ensure integrity that if a has buddy b then b has buddy a for all a and b.
The fact that one moment after befriending two objects they might be unfriended by another thread is presumably what you intend or addressed by other synchronization.
Note also that when you're befriending and may unfriend the friends of the new friends you need to lock ALL the objects at once.
That is the two 'to be' friends and their current friends (if any).
Consequently you need to lock 2,3 or 4 mutexes.
std::lock unfortunately doesn't take an array but there is a version that does that in boost or you need to address it by hand.
To clarify, I'm reading the examples of possible destructors as models. Synchronization on the same locks would be required in all the relevant members (e.g. befriend(), swap() and unfriend() if that is required). Indeed the issue of locking 2,3 or 4 applies to the befriend() member.
Furthermore the destructor is probably the worst example because as mentioned in a comment it's illogical that an object is destructible but may be in lock contention with another thread. Some synchronization surely needs to exist in the wider program to make that impossible at which point the lock in the destructor is redundant.
Indeed a design which ensures Guy objects have no buddy before destruction would seem like a good idea and a debug pre-condition that checks assert(buddy==nullptr) in the destructor. Sadly that can't be left as a run-time exception because throwing exceptions in destructors can cause program termination (std::terminate()).
In fact the real challenge (which may depend on the surrounding program) is how to unfriend when befriending. That would appear to require a try-retreat loop:
Lock a and b.
Find out if they have buddies.
If they're already buddies - you're done.
If they have other buddies, unlock a & b, and lock a and b and their buddies (if any).
Check that the buddies haven't changed, if they have go again.
Adjust the relevant members.
It's a question for the surrounding program whether that risks live-lock but any try-retreat method suffers the same risk.
What won't work is std::lock() a & b then std::lock() the buddies because that does risk deadlock.
So to answer the question - yes, it is possible without a global lock but that depends on the surrounding program. It may be in a population of many Guy objects contention is rare and liveness is high.
But it may be that there are a small number of objects that are hotly contended (possibly in a large population) that results in a problem. That can't be assessed without understanding the wider application.
One way to resolve that would be lock escalation which in effect piecemeal falls back to a global lock. In essence that would mean if there were too many trips round the re-try loop a global semaphore would be set ordering all threads to go into global lock mode for a while. A while might be a number of actions or a period of time or until contention on the global lock subsides!
So the final answer is "yes it's absolutely possible unless it doesn't work in which case 'no'".

std::lock_guard example, explanation on why it works

I've reached a point in my project that requires communication between threads on resources that very well may be written to, so synchronization is a must. However I don't really understand synchronization at anything other than the basic level.
Consider the last example in this link: http://www.bogotobogo.com/cplusplus/C11/7_C11_Thread_Sharing_Memory.php
#include <iostream>
#include <thread>
#include <list>
#include <algorithm>
#include <mutex>
using namespace std;
// a global variable
std::list<int>myList;
// a global instance of std::mutex to protect global variable
std::mutex myMutex;
void addToList(int max, int interval)
{
// the access to this function is mutually exclusive
std::lock_guard<std::mutex> guard(myMutex);
for (int i = 0; i < max; i++) {
if( (i % interval) == 0) myList.push_back(i);
}
}
void printList()
{
// the access to this function is mutually exclusive
std::lock_guard<std::mutex> guard(myMutex);
for (auto itr = myList.begin(), end_itr = myList.end(); itr != end_itr; ++itr ) {
cout << *itr << ",";
}
}
int main()
{
int max = 100;
std::thread t1(addToList, max, 1);
std::thread t2(addToList, max, 10);
std::thread t3(printList);
t1.join();
t2.join();
t3.join();
return 0;
}
The example demonstrates how three threads, two writers and one reader, accesses a common resource(list).
Two global functions are used: one which is used by the two writer threads, and one being used by the reader thread. Both functions use a lock_guard to lock down the same resource, the list.
Now here is what I just can't wrap my head around: The reader uses a lock in a different scope than the two writer threads, yet still locks down the same resource. How can this work? My limited understanding of mutexes lends itself well to the writer function, there you got two threads using the exact same function. I can understand that, a check is made right as you are about to enter the protected area, and if someone else is already inside, you wait.
But when the scope is different? This would indicate that there is some sort of mechanism more powerful than the process itself, some sort of runtime environment blocking execution of the "late" thread. But I thought there were no such things in c++. So I am at a loss.
What exactly goes on under the hood here?
Let’s have a look at the relevant line:
std::lock_guard<std::mutex> guard(myMutex);
Notice that the lock_guard references the global mutex myMutex. That is, the same mutex for all three threads. What lock_guard does is essentially this:
Upon construction, it locks myMutex and keeps a reference to it.
Upon destruction (i.e. when the guard's scope is left), it unlocks myMutex.
The mutex is always the same one, it has nothing to do with the scope. The point of lock_guard is just to make locking and unlocking the mutex easier for you. For example, if you manually lock/unlock, but your function throws an exception somewhere in the middle, it will never reach the unlock statement. So, doing it the manual way you have to make sure that the mutex is always unlocked. On the other hand, the lock_guard object gets destroyed automatically whenever the function is exited – regardless how it is exited.
myMutex is global, which is what is used to protect myList. guard(myMutex) simply engages the lock and the exit from the block causes its destruction, dis-engaging the lock. guard is just a convenient way to engage and dis-engage the lock.
With that out of the way, mutex does not protect any data. It just provides a way to protect data. It is the design pattern that protects data. So if I write my own function to modify the list as below, the mutex cannot protect it.
void addToListUnsafe(int max, int interval)
{
for (int i = 0; i < max; i++) {
if( (i % interval) == 0) myList.push_back(i);
}
}
The lock only works if all pieces of code that need to access the data engage the lock before accessing and disengage after they are done. This design-pattern of engaging and dis-engaging the lock before and after every access is what protects the data (myList in your case)
Now you would wonder, why use mutex at all, and why not, say, a bool. And yes you can, but you will have to make sure that the bool variable will exhibit certain characteristics including but not limited to the below list.
Not be cached (volatile) across multiple threads.
Read and write will be atomic operation.
Your lock can handle situation where there are multiple execution pipelines (logical cores, etc).
There are different synchronization mechanisms that provide "better locking" (across processes versus across threads, multiple processor versus, single processor, etc) at a cost of "slower performance", so you should always choose a locking mechanism which is just about enough for your situation.
Just to add onto what others here have said...
There is an idea in C++ called Resource Acquisition Is Initialization (RAII) which is this idea of binding resources to the lifetime of objects:
Resource Acquisition Is Initialization or RAII, is a C++ programming technique which binds the life cycle of a resource that must be acquired before use (allocated heap memory, thread of execution, open socket, open file, locked mutex, disk space, database connection—anything that exists in limited supply) to the lifetime of an object.
C++ RAII Info
The use of a std::lock_guard<std::mutex> class follows the RAII idea.
Why is this useful?
Consider a case where you don't use a std::lock_guard:
std::mutex m; // global mutex
void oops() {
m.lock();
doSomething();
m.unlock();
}
in this case, a global mutex is used and is locked before the call to doSomething(). Then once doSomething() is complete the mutex is unlocked.
One problem here is what happens if there is an exception? Now you run the risk of never reaching the m.unlock() line which releases the mutex to other threads.
So you need to cover the case where you run into an exception:
std::mutex m; // global mutex
void oops() {
try {
m.lock();
doSomething();
m.unlock();
} catch(...) {
m.unlock(); // now exception path is covered
// throw ...
}
}
This works but is ugly, verbose, and inconvenient.
Now lets write our own simple lock guard.
class lock_guard {
private:
std::mutex& m;
public:
lock_guard(std::mutex& m_):(m(m_)){ m.lock(); } // lock on construction
~lock_guard() { t.unlock(); }} // unlock on deconstruction
}
When the lock_guard object is destroyed, it will ensure that the mutex is unlocked.
Now we can use this lock_guard to handle the case from before in a better/cleaner way:
std::mutex m; // global mutex
void ok() {
lock_guard lk(m); // our simple lock guard, protects against exception case
doSomething();
} // when scope is exited our lock guard object is destroyed and the mutex unlocked
This is the same idea behind std::lock_guard.
Again this approach is used with many different types of resources which you can read more about by following the link on RAII.
This is precisely what a lock does. When a thread takes the lock, regardless of where in the code it does so, it must wait its turn if another thread holds the lock. When a thread releases a lock, regardless of where in the code it does so, another thread may acquire that lock.
Locks protect data, not code. They do it by ensuring all code that accesses the protected data does so while it holds the lock, excluding other threads from any code that might access that same data.

Query std::mutex for lock state

I have a situation where I'd like to do something like that shown below, but there doesn't seem to be a way of querying the mutex without changing its state. I don't want the someFunctionCalledRepeatedlyFromAnotherThread() to hang around waiting for the mutex to free up if it is locked. It must return immediately after performing some alternative action. I'm guessing this omission is there for safety, as the lock may free up in the time between querying it and the function returning. In my case, bad stuff will not happen if the lock is freed while doSomeAlternativeAction() is happening. The fact I'm in this situation probably means I'm doing something wrong, so how should I change my design?
class MyClass
{
std::mutex initMutex;
public:
void someInitializationFunction()
{
std::lock_guard<std::mutex> lock(initMutex);
// Do some work
}
void someFunctionCalledRepeatedlyFromAnotherThread()
{
if (initMutex.isLocked())
{
doSomeAlternativeAction();
return;
}
// otherwise . . .
std::lock_guard<std::mutex> lock(initMutex);
// carry on with work as usual
}
}
Asking mutex for its state is useless: it may be unlocked now, but by the time you get around to lock it, it may be locked. So it does not have such method.
It does, however, have a method try_lock() which locks it if it is not locked and returns true if it acquired the lock and false otherwise. And std::unique_lock (the more advanced version of std::lock_guard) has option to call it.
So you can do:
void someFunctionCalledRepeatedlyFromAnotherThread()
{
std::unique_lock<std::mutex> lock(initMutex, std::try_to_lock);
if(!lock.owns_lock())
{
doSomeAlternativeAction();
return;
}
// otherwise ... go ahead, you have the lock
}
Sounds like you want to use std::unique_lock instead of std::lock_guard. The try_lock method works similar to the TryEnterCriticalSection on Windows, whereby the function will atomically acquire the lock and return 'true' if it can, or just return 'false' if the lock cannot be acquired (and will not block). Refer to http://msdn.microsoft.com/en-us/library/hh921439.aspx and http://en.cppreference.com/w/cpp/thread/unique_lock/try_lock. Note that unique_lock also has other members available for trying to lock such as try_lock_for and try_lock_until.

How should I lock a wxMutex in one function and unlock it in another?

I'm supposed to implement my own logging class for use in a program with two threads, the main one and a joinable processing thread. I don't want either thread to use the logger while the other is using it, so I figured I'd use a wxMutex. The logger has to act like a C++ ostream with operator<<, except that a stream manipulator function (std::endl, for example) will indicate the end of the logger's output. I think I need a recursive mutex so that the same thread can continue outputting when the mutex is locked.
The problem (I think) is that the mutex doesn't get fully unlocked, so when the other thread tries to output to the logger, it deadlocks.
Is there something in my code that I'm missing?
class Logger{
private:
std::ostream* out;
wxMutex* mut;
....
public:
template<class T>
Logger& operator<<(T str){ // accept any type of input and lock outputting until finished
if(out){
if(mut->TryLock() == wxMUTEX_BUSY){ // if we didn't get lock
mut->Lock(); // we block
}
if(out){
(*out) << str;
out->flush();
}
//mut->Unlock(); // leave locked until done outputting (use std::endl or similar)
}
return *this;
}
// accept stream manipulators and unlock stream output
Logger& operator<<(std::ostream& (*pf) (std::ostream&)){
if(out){
if(mut->TryLock() == wxMUTEX_BUSY){
mut->Lock();
}
(*out) << pf;
out->flush();
while(mut->Unlock()!= wxMUTEX_UNLOCKED);
}
return *this;
}
};
If you are worried about threading issues, you could instead make a macro that makes sure the mutex is acquired before the output and released after the output.
Something like:
#define LOG(logger, output) \
do { logger.lock(); logger << output; logger.unlock(); } while (0)
Logger my_logger;
int some_integer = 5;
LOG(my_logger, "Hello world!" << some_integer << std::endl);
First of all, in wxWidgets 2.9 wxLog itself is MT-safe and you can have independent log targets for each thread so perhaps you could just use it instead of writing your own.
Second, using TryLock() is suspicious, if you want to be able to re-lock the mutex already belonging to the current thread, you should use wxMUTEX_RECURSIVE when creating the mutex and simply use Lock() nevertheless. However personally I believe that using recursive mutexes is a bad idea because it makes your MT-code less clear and more difficult to reason about and this is almost invariably catastrophic.
Finally, the whole idea of relying on someone to call << endl is just wrong. It's too easy to forget to do it somewhere and leave the mutex locked preventing all the other threads from continuing. You absolutely should create a proxy object locking the mutex in its ctor and unlocking it in its dtor and use it to ensure that the mutex is always unlocked at the end of statement doing the logging. I think that by using this technique you should avoid the need for recursive mutexes too.
I might be wrong but it looks to me that you are trying to lock the mutex when it is in use already.
if(mut->TryLock() == wxMUTEX_BUSY) // if TryLock() returns wxMUTEX_BUSY another thread is using it.
{
mut->Lock(); // A dead lock situation could be detected here because Lock() also returns an error code.
}
TryLock() usually attempts to acquire the mutex without blocking. So, if the mutex is already busy on that call, it means that another thread is using it.
You could have a look to this link from wxMutex which explains how each functions works. Their function returns values, so you could use that to see what's going wrong in your program.
See the doc from their website below.
wxMutex::Lock
wxMutexError Lock()
Locks the mutex object.
Return value
One of:
wxMUTEX_NO_ERROR There was no error.
wxMUTEX_DEAD_LOCK A deadlock situation was detected.