zl程序教程

您现在的位置是:首页 >  其他

当前栏目

【C++11】 让多线程开发变得简单--条件变量

2023-03-14 22:42:13 时间

条件变量是C++11中提供的又一种线程同步机制,它可以阻塞一个或者多个线程,直到收到其它线程发出的超时或者通知才能够唤醒正在等待的线程,条件变量需要和互斥量配合使用,在C++ 11中共提供了两种条件变量。

  • condition_variable:配合std::unique_lock<std::mutex>使用
  • condition_variable_any:和lock、unlock配合使用,使用相对比较灵活但是性能也会比较差一点。

条件变量使用过程如下:

  • 获取互斥量
  • 循环检查条件,如果条件不满足则一直阻塞,反之继续执行
  • 线程执行完后调用notify_one或者notify_all唤醒等待的线程

在实际编码中,可以使用条件变量实现一个同步队列,同步队列可以作为线程安全的数据共享区,用户线程之间的数据读取,代码如下:

template<typename T>
class SynQueue
{
    bool IsFull() const
{
        return m_queue.size() ==  m_maxSize;
    }
    
    bool IsEmpty() const
{
        return m_queue.empty();
    }
public:
    SysQueue(int maxSize):m_maxSize(maxSize)
    {
        
    }
    
    void Put(const T &x)
{
        std::lock_guard<std::mutex> locker(m_mutex);
        while(IsFull())
        {
            cout<<"缓冲区满,需要等....."<<endl;
            m_notFull.wait(m_mutex);
        }
        
        m_queue.push_back(x);
        m_notEmpty.notify_one();
    }
    
    void Take(T &x)
{
         std::lock_guard<std::mutex> locker(m_mutex);
         while(IsEmpty())
         {
             cout<<"缓冲区空,需要等....."<<endl;
            m_notFull.wait(m_mutex);
         }
         
         x = m_queue.front();
         m_queue.pop_front();
         m_notFull.notify_one();
    }
    
    bool Empty()
{
        std::lock_guard<std::mutex> locker(m_mutex);
        return m_queue.empty();
    }
    
    bool Full()
{
        std::lock_guard<std::mutex> locker(m_mutex);
        return m_queue.size()==m_maxSize;
    }
    
    size_t Size()
    {
         std::lock_guard<std::mutex> locker(m_mutex);
        return m_queue.size();
    }
    
    int Count()
{
        return m_queue.size();
    }
private:
    std::list<T> m_queue;
    std::mutex m_mutex;
    std::condition_variable_any m_notEmpty;
    std::condition_variable_any m_notFull;
    int m_maxSize;
};

上面的代码实现了一个同步队列的功能,在队列没有满的情况下可以插入数据,如果队列满则会调用m_notFull进行阻塞等待其它线程发送通知,如果队列为空,则不能取出数据,会调用m_notEmpty条件变量进行阻塞,等待其它线程发送通知,然后继续执行。