Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++: Function that locks mutex for other function but can itself be executed in parallel

I have a question regarding thread safety and mutexes. I have two functions that may not be executed at the same time because this could cause problems:

std::mutex mutex;

void A() {
    std::lock_guard<std::mutex> lock(mutex);
    //do something (should't be done while function B is executing)
}

T B() {
    std::lock_guard<std::mutex> lock(mutex);
    //do something (should't be done while function A is executing)
    return something;
}

Now the thing is, that function A and B should not be executed at the same time. That's why I use the mutex. However, it is perfectly fine if function B is called simultaneously from multiple threads. However, this is also prevented by the mutex (and I don't want this). Now, is there a way to ensure that A and B are not executed at the same time while still letting function B be executed multiple times in parallel?

like image 963
bweber Avatar asked Sep 28 '22 20:09

bweber


1 Answers

If C++14 is an option, you could use a shared mutex (sometimes called "reader-writer" mutex). Basically, inside function A() you would acquire a unique (exclusive, "writer") lock, while inside function B() you would acquire a shared (non-exclusive, "reader") lock.

As long as a shared lock exists, the mutex cannot be acquired exclusively by other threads (but can be acquired non-exclusively); as long as an exclusive locks exist, the mutex cannot be acquired by any other thread anyhow.

The result is that you can have several threads concurrently executing function B(), while the execution of function A() prevents concurrent executions of both A() and B() by other threads:

#include <shared_mutex>

std::shared_timed_mutex mutex;

void A() {
    std::unique_lock<std::shared_timed_mutex> lock(mutex);
    //do something (should't be done while function B is executing)
}

T B() {
    std::shared_lock<std::shared_timed_mutex> lock(mutex);
    //do something (should't be done while function A is executing)
    return something;
}

Notice, that some synchronization overhead will always be present even for concurrent executions of B(), and whether this will eventually give you better performance than using plain mutexes is highly dependent on what is going on inside and outside those functions - always measure before committing to a more complicated solution.

Boost.Thread also provides an implementation of shared_mutex.

like image 113
Andy Prowl Avatar answered Oct 07 '22 01:10

Andy Prowl