Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is std::mutex fair? [duplicate]

Tags:

c++

c++11

mutex

As the question states, is std::mutex fair? i.e., if thread A locked the mutex and then B and C call 'lock()' on it in this order, will they obtain the lock on the mutex in this same order or is the order unspecified?

The documentation doesn't address this at all.

like image 658
mort Avatar asked Jan 13 '23 23:01

mort


2 Answers

The standard (§30.4) does not mention anything about requirements regarding fairness between contending threads on a mutex, so it might be or might not be fair.

In practice std::mutex implementations will probably use whatever mutex implementation their platform provides, which are moslty unfair, as this is usually simpler and more efficient. On windows e.g. mutexes are mostly fair, but not always. Some implementations e.g. Thread Building Block provide special mutexes that are fair, but these are not based on the OSes native mutexes, and are usually implemented as spin-locks (which have their own caveats).

like image 96
ronag Avatar answered Jan 21 '23 09:01

ronag


If the documentation does not address it, We could suggest that is unspecified and if it is not specified, you may have some surprise gessing that they obtain the lock in the same order they ask...

In order to be sure that the threads obtain the mutex in the same order they ask, I suggest you to take a look at std::condition_variable or at std::condition_variable_any.

They are both declared in <condition_variable> library header. In both cases, they need to work with a mutex in order to provide appropriate synchronization.

Here is a little example of how you can use it :

#include <mutex>
#include <condition_variable>

std::mutex mut;
std::queue<dummyData> data;
std::condition_variable cond;

void dummyDataPrepare()
{
    while( more_data_in_preparation() )
    {
        std::lock_guard<std::mutex> lo( mut );
        // doing many things on data
        cond.notify_one();
    }
}

void dummyDataProcessingThread()
{
    while( true )
    {
        std::unique_lock<std::mutex> lo( mut );
        cond.wait( lo,
            []{ return !data.empty(); });
        // Do whatever you want ...
        lo.unlock();
    }
}

This example shows how you can wait for some data to process before doing something on it.

like image 41
Pierre Fourgeaud Avatar answered Jan 21 '23 10:01

Pierre Fourgeaud