CodeBricks
CodeBricks

Reputation: 1801

How frequently does mutex::lock() check for the unlocked state if it's already locked by another thread?

According to cppreference, constructing an std::lock_guard with a std::mutex parameter calls the lock() method of that mutex.

According to cplusplus, regarding mutex’s lock() method:

If the mutex is locked by another thread, execution of the calling thread is blocked until unlocked by the other thread...

I'm not sure if the titular question is worded properly, so I put it in the context of the below code.

I wanted to test this and see if a calling thread actually waits for the unlocking instead of terminating execution of its callable (e.g. function, functor, lambda) and/or throwing an exception. The following code has two threads t1 and t2, each constructed with a pointer to the same function foo. Each call to foo will sleep_for a certain amount of time, determined by foo's unsigned parameter num, before executing the lock-protected code. The lock-protected code itself contains another sleep_for period, to make any blocked execution period more obvious:

#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>

std::mutex m;

void foo(unsigned num) {
    std::this_thread::sleep_for(std::chrono::milliseconds(num * 10));
    std::lock_guard<std::mutex> guard(m);
    std::this_thread::sleep_for(std::chrono::milliseconds(3000));
    std::cout << num << std::endl;
}

int main() {
    std::thread t1(foo, 10);
    std::thread t2(foo, 5);
    t1.join();
    t2.join();
}

Console Output:

5
10

It takes about/at least 3.05 seconds for the 5 to output. It takes about/at least an additional 3 seconds for the 10 to output. This means t2 gets to execute the protected code first, since it has the lesser wait time prior to the locking of the mutex.

I’m assuming once the call to foo from thread t1 gets to the lock_guard line and finds the mutex had already been locked by t2, t1 doesn’t terminate execution or throw an exception. t1 just waits for it to be unlocked.

How frequently does std::mutex::lock() or std::lock_guard make this check for the unlocking? How costly is the check? Is the check implemented like the following?

while (some_mutex.try_lock() == false) {
    std::this_thread::sleep_for(std::chrono::milliseconds(1))
}
// execute lock-protected code

Upvotes: 0

Views: 686

Answers (2)

user207421
user207421

Reputation: 311048

How frequently does std::mutex::lock() or std::lock_guard make this check for the unlocking?

It doesn't. It blocks inside the operating system until the resource is released. Any operating system that implemented this by spinning would be cause for complaint.

Upvotes: 4

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385385

Mutexes are typically provided by the OS, meaning your OS's threading model is responsible for all of this. These details are not specified or even implemented by C++ at all.

As such, to a degree, it will depend on a number of factors such as CPU load across all processes, relative process priority, relative thread priority...

There's just far too much going on to give a clear-cut answer for you, even if such a thing would be useful.

Upvotes: 2

Related Questions