It's possible to not want the thread to block and wait for the mutex object to become available: for example, when one just wants to know whether a request is already being handled by another thread, and there's no use in waiting for it to finish.
For this, a mutex comes with the try_lock() function which does exactly that.
In the following example, we can see two threads trying to increment the same counter, but with one incrementing its own counter whenever it fails to immediately obtain access to the shared counter:
#include <chrono>
#include <mutex>
#include <thread>
#include <iostream>
std::chrono::milliseconds interval(50);
std::mutex mutex;
int shared_counter = 0;
int exclusive_counter = 0;
void worker0() {
std::this_thread::sleep_for(interval);
while (true) {
if (mutex.try_lock()) {
std::cout << "Shared (" << job_shared << ")\n";
mutex.unlock();
return;
}
else {
++exclusive_counter;
std::cout << "Exclusive (" << exclusive_counter << ")\n";
std::this_thread::sleep_for(interval);
}
}
}
void worker1() {
mutex.lock();
std::this_thread::sleep_for(10 * interval);
++shared_counter;
mutex.unlock();
}
int main() {
std::thread t1(worker0);
std::thread t2(worker1);
t1.join();
t2.join();
}
Both threads in this preceding example run a different worker function, yet both have in common the fact that they sleep for a period of time, and try to acquire the mutex for the shared counter when they wake up. If they do, they'll increase the counter, but only the first worker will output this fact.
The first worker also logs when it did not get the shared counter, but only increased its exclusive counter. The resulting output might look something like this:
Exclusive (1)
Exclusive (2)
Exclusive (3)
Shared (1)
Exclusive (4)