C++ Thread学习四 (使用条件变量condition_variable来实现生产者消费者)

仍然接着我的上一篇博客里的内容https://blog.csdn.net/mcc12356/article/details/106825972(感兴趣可以去看看),主要是一个写线程往共享队列里写数据,另一个读线程从队列里读数据。当时使用了mutex来实现了对共享队列的保护,但是那里会有一点问题,如果共享队列为空,读队列线程读取不到数据,但仍然可能获取了锁导致写线程被阻塞。那么能否有一种方法使得读线程只有在队列不为空时才能获取锁呢?这时条件变量(condition_variable)就派上了用场。

条件变量介绍:

顾名思义,条件变量是一个类,他起到的作用阻塞某一个线程,当满足某一个条件时该线程被唤醒继续执行,要配合互斥量mutex使用。

新建一个条件变量:

condition_variable my_condV;

wait()函数

unique_lock mutexObj(my_mutex);

my_condV.wait(mutexObj, [this] {
            if (!msgQueue.empty()) return true;
            return false;
        });                       

首先需要一个unique_lock对象,wait函数第一个参数是此unique_lock对象,第二个参数是一个函数(这里写了一个lambda function),含义是如果队列不为空,就可以继续执行后面的语句。如果队列为空,那么就会立即释放my_mutex(这样其他线程可以获取到my_mutex),然后等待被其他线程唤醒后再进行判断。这里第二个参数可以缺省,相当于return false(含义是默认阻塞),被唤醒后return true(可以继续执行)。

notify_one()或者notify_all()

唤醒函数,一般是另一个线程。在本例中就是生产者线程,当队列里放入数据后通知消费者线程。notify_one是唤醒任意一个wait的线程,notify_all是唤醒所有wait的线程。

完整代码如下:

#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

class A
{
public:
    // 用于向队列里产生数据
    void inMsg()
    {
        for (int i = 0; i < 10000; i++)
        {
            int x = rand();
            unique_lock mutexObj(my_mutex);
            msgQueue.push_back(x);
            // 队列此时不为空,通知读取线程可以从队列里读取数据
            my_condV.notify_one();
            cout << "write " << x << " into msg queue!\n";
            // 提前解除对共享队列的锁定,这样其他线程可以对共享队列进行操作
            my_mutex.unlock();
            // ...其他操作
        }
        return ;
    }
    
    // 用于从队列里读取数据
    void outMsg()
    {
        while (true)
        {
            unique_lock mutexObj(my_mutex);
            // 判断队列是否为空,如果为空就释放之前获取的my_mutex并阻塞等待唤醒,这样其他线程可以获取到my_mutex。如果队列不为空就继续执行
            my_condV.wait(mutexObj, [this]{
                if (!msgQueue.empty()) return true;
                return false;
            });
            
            int msg = msgQueue.front();
            msgQueue.pop_front();
            cout << "read " << msg << " from msg queue!\n";
            // 提前解除对共享队列的锁定,这样其他线程可以对共享队列进行操作
            my_mutex.unlock();
            // ...其他操作
        }
        return ;
    }
private:
    list msgQueue;
    mutex my_mutex;
    condition_variable my_condV;
};


int main(int argc, const char * argv[]) {
    A myobj;
    thread inThread(&A::inMsg,&myobj);
    thread outThread(&A::outMsg,&myobj);
    inThread.join();
    outThread.join();
    return 0;
}

部分运行结果截图:

C++ Thread学习四 (使用条件变量condition_variable来实现生产者消费者)_第1张图片

 

你可能感兴趣的:(C++,服务器,c++)