c++c++17mutexstdmutex

c++ mutexes that not blocks code from inside, but allow to block it from outside


I'm trying to solve the next problem:

There are two types of functions. The first type can execute from different threads simultaneously (for example - read data from container). The second one must block all threads inside first-type-function until some operation done (for example - change container).

I am sure this is an easy task, but I can't find a solution. Can anyone please help me?

This is simple example. I expect threads to stop output for 1 second every 3 seconds (I'm aware that this code is unsafe (cout from different threads), but it's just an simple example)

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

using namespace std;


void f() {
    // TODO: wait if g() locked this
    cout << "Hello from thread " << this_thread::get_id() << endl;
    this_thread::sleep_for(100ms);
}

void g() {
    // TODO: some lock for f()
    cout << "All threads must sleep at night" << endl;
    this_thread::sleep_for(1000ms);
    // TODO: unlock
}

int main() {
    thread t1([]() { for (;;) f(); });
    thread t2([]() { for (;;) f(); });
    thread t3([]() { for (;;) f(); });

    for (;;) {
        this_thread::sleep_for(3000ms);
        g();
    }

    return 0;
}

Solution

  • This is a common pattern best solved using reader/writer locks. In C++ you want to use std::shared_lock and imagine that f is a reader and g is a writer.

    Declare variable:

    std::shared_mutex mutex;
    

    In f:

    // Multiple threads can enter the shared lock (readers).
    std::shared_lock lock(mutex);
    

    In g:

    // Only one thread can enter the unique lock (writers).
    std::unique_lock lock(mutex);