Home > Back-end >  How to get two threads to work on the shared resource
How to get two threads to work on the shared resource

Time:07-11

I have a С class that has a databases_list_ vector defined.
This vector contains database objects.

I need to make two functions that will run on separate threads.
And each function will use the databases_list_ vector.
That is, this vector is a shared resource for my functions.
In this case, I don't know the correct approach to secure the share so that every thread can use it.

// This is class Worker
class Worker {
private:
    std::thread check_oo_thread_{}; // thread #1
    std::thread check_db_thread_{}; // thread #2
    void check_oo();                // func #1
    void check_db();                // func #2

    std::vector<std::unique_ptr<database>> databases_list_; // This is a shared resource
    bool is_work_{ false };
}
// Here I am running two threads
void Worker::start() {
    is_work_ = true;
    check_oo_thread_ = std::thread(&Worker::check_oo, this);
    check_db_thread_ = std::thread(&Worker::check_db, this);
}

And here are two functions that use the databases_list_ vector in different threads. The difference is that these functions get different data from the database - it depends on the command_type parameter

// In this function, each database object is called in turn
void Worker::check_oo() {
    while (is_work_) {
        for (auto& db : databases_list_) {
            auto db_cfg = db->get_cfg();
            data_handler_.set_database(db_cfg.db_server);
            auto db_respond = db->send_command(receive_cmd, command_type::get_data);
        }
        std::this_thread::sleep_for(std::chrono::seconds(processing_period_1));
    }
}

// In this function, each database object is called in turn
void Worker::check_db() {
    while (is_work_) {
        for (auto& db : databases_list_) {
            auto db_cfg = db->get_cfg();
            data_handler_.set_database(db_cfg.db_server);
            auto db_respond = db->send_command(receive_cmd, command_type::get_stat);
        }
        std::this_thread::sleep_for(std::chrono::seconds(processing_period_2));
    }
}

This is a tricky case for me and I can't figure out how to get two threads to work on the shared resource databases_list_.

CodePudding user response:

You can lock a std::mutex every time you want to access the shared resource. You also access is_work_ from multiple threads and I therefore suggest making that std::atomic<bool> is_work_ instead.

#include <atomic>
#include <mutex>

class Worker {
private:
    std::thread check_oo_thread_{}; // thread #1
    std::thread check_db_thread_{}; // thread #2
    mutable std::mutex m_mtx;       // use this to sync actions on your resource
    std::atomic<bool> is_work_{};   // now atomic
    
    void check_oo() {
        while(is_work_) {
            {
                std::lock_guard<std::mutex> lock{m_mtx}; // locks the mutex
                // use databases_list_ here
            }                                            // mutex is unlocked here
            std::this_thread::sleep_for(...);
        }
    }        
    void check_db() {
        while(is_work_) {
            {
                std::lock_guard<std::mutex> lock{m_mtx};
                // use databases_list_ here
            }
            std::this_thread::sleep_for(...);
        }
    }

    std::vector<std::unique_ptr<database>> databases_list_;
};
  • Related