C++11 Multithreading - Condition Variable

Condition Variable is a kind Event used for signaling between 2 or more threads. One thread can wait for it to get signaled, while other thread can signal this.

A condition variable is generally used to avoid busy waiting (looping repeatedly while checking a condition) while waiting for a resource to become available.

 

Why Condition Variables?

A condition variable allows a thread to be signaled when something of interest to that thread occurs.

By itself, a mutex doesn't do this.

If you just need mutual exclusion, then condition variables don't do anything for you. However, if you need to know when something happens, then condition variables can help.

For example, if you have a queue of items to work on, you'll have a mutex to ensure the queue's internals are consistent when accessed by the various producer and consumer threads. However, when the queue is empty, how will a consumer thread know when something is in there for it to work on? Without something like a condition variable it would need to poll the queue, taking and releasing the mutex on each poll (otherwise a producer thread could never put something on the queue).

Using a condition variable lets the consumer find that when the queue is empty it can just wait on the condition variable indicating that the queue has had something put into it. No polling - that thread does nothing until a producer puts something in the queue, then signals the condition that the queue has a new item.

 

Usage

Wait(unique_lock<mutex>& lck, Predicate pred) - It makes the current thread to block until the condition variable get signaled or a spurious wake up happens.

notify_one() - If any threads are waiting on same conditional variable object then  notify_one unblocks one of the waiting threads.

notify_all() - If any threads are waiting on same conditional variable object then  notify_all unblocks all of the waiting threads.

 

An example: https://thispointer.com//c11-multithreading-part-7-condition-variables-explained/

#include <thread>
#include <mutex>
#include <condition_variable>
using namespace std;

class Application{
    std::mutex m;
    std::condition_variable cv;
    bool dataLoaded;
public:
    Application():dataLoaded(false){}
    bool isDataLoaded(){return dataLoaded;}
    
    void loadData(){
        // Make This Thread sleep for 1 Second
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        std::cout<<"Loading Data from XML"<<std::endl;
        // Lock The Data structure
        std::lock_guard<std::mutex> guardLock(m);
        // Set the flag to true, means data is loaded
        dataLoaded = true;
        // Notify the condition variable
        cv.notify_one();
    }
    
    void mainTask(){
        std::cout<<"Do Some Handshaking"<<std::endl;
        // Acquire the lock
        std::unique_lock<std::mutex> lock(m);
        // Start waiting for the Condition Variable to get signaled
        // Wait() will internally release the lock and make the thread to block
        // As soon as condition variable get signaled, resume the thread and
        // again acquire the lock. Then check if condition is met or not
        // If condition is met then continue else again go in wait.
        cv.wait(lock, std::bind(&Application::isDataLoaded, this));
        std::cout<<"Do Processing On loaded Data"<<std::endl;
    }
};

int main()
{
   Application app;
   std::thread thread_1(&Application::mainTask, &app);
   std::thread thread_2(&Application::loadData, &app);
   thread_2.join();
   thread_1.join();
   return 0;
}

 

Reference

https://en.cppreference.com/w/cpp/thread/condition_variable

https://stackoverflow.com/questions/4742196/advantages-of-using-condition-variables-over-mutex

https://thispointer.com//c11-multithreading-part-6-need-of-event-handling/

https://thispointer.com//c11-multithreading-part-7-condition-variables-explained/

Guess you like

Origin www.cnblogs.com/hankunyan/p/11669382.html