美文网首页
C++11 使用std::lock_guard和std::mut

C++11 使用std::lock_guard和std::mut

作者: FredricZhu | 来源:发表于2020-12-25 17:00 被阅读0次

关键技术点:

  1. 多线程环境下,cout因为拥有缓冲buffer,可能会写出失败,可以先使用stringstream进行缓存,在输出对象销毁时,在析构函数中使用std::cerr输出
  2. C++ 11 条件变量和互斥体的简单用法
  3. C++ 11 多线程的简单用法
    实现代码
    scout.hpp
#ifndef _SCOUT_HPP_
#define _SCOUT_HPP_
#include <mutex>
#include <iostream>
#include <sstream>

class Scout {
    std::ostringstream st;
    // Endl结束符的形式
    using endlFunc = std::ostream& (*)(std::ostream&);

    public:
        // 处理普通模板类输出
        template <typename T>
        Scout& operator<<(const T& t) {
            st << t;
            return *this;
        }

        // 处理换行符
        Scout& operator<<(endlFunc endlF) {
            st << endlF;
            return *this;
        }

        ~Scout() {
            std::string s = st.str();
            // std::cerr不存buffer 直接输出
            std::cerr << s;
        }
};

// 定义一个宏,方便输出
#define scout Scout()

#endif

sync_queue.hpp

#ifndef _SYNC_QUEUE_HPP_
#define _SYNC_QUEUE_HPP_
#include <list>
#include <mutex>
#include <thread>
#include <condition_variable>
#include <iostream>
#include "scout.hpp"

template <typename T> 
class SyncQueue {

    private:
        // 队列缓冲区已满  
        bool isFull() const {
            return m_queue.size() == m_maxSize;
        }

        // 队列缓冲区为空
        bool isEmpty() const {
            return m_queue.empty();
        }

    public:
        SyncQueue(int maxSize): m_maxSize(maxSize) {}

        // 入队操作
        void Put(const T& x) {
            std::lock_guard<std::mutex> lock(m_mutex);

            while(isFull()) {
                scout << "缓冲区满了,需要等待..." << std::endl;
                m_notFull.wait(m_mutex);
            }
            m_queue.emplace_back(x);
            m_notEmpty.notify_one();
        }

        // 出队操作
        void Take(T& x) {
            std::lock_guard<std::mutex> lock(m_mutex);
            while(isEmpty()) {
                scout << "缓冲区为空了,需要等待..." << std::endl;
                m_notEmpty.wait(m_mutex); 
            }
            x = m_queue.front();
            m_queue.pop_front();
            m_notFull.notify_one();
        }
        
        // 带锁的Empty版本
        bool Empty() {
            std::lock_guard<std::mutex> lock(m_mutex);
            return m_queue.empty();
        }

        // 带锁的Full版本
        bool Full() {
            std::lock_guard<std::mutex> lock(m_mutex);
            return m_queue.size() == m_maxSize;
        }

        // 带锁的size版本
        int Size() {
            std::lock_guard<std::mutex> lock(m_mutex);
            return m_queue.size();
        }

        // 不带锁的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;  // 同步队列的最大大小 

};

#endif

main.cpp

#include "sync_queue.hpp"
#include <thread>
#include <iostream>
#include <mutex>
#include <cstdlib>

using std::cout;
using std::endl;

SyncQueue<int> syncQueue(5);

void PutDatas() {
    for(int i=0; i<20; i++) {
        syncQueue.Put(888);
    }
}

void TakeDatas() {
    int x = 0;
    for(int i=0; i<20; i++) {
        syncQueue.Take(x);
        scout << x << " ";
    }
    scout << endl;
}


int main(void) {
    std::thread t1(PutDatas);
    std::thread t2(TakeDatas);

    t1.join();
    t2.join();

    cout << "请按任意键继续..." << endl;
    getchar();
    return 0;
}

程序输出如下


图片.png

相关文章

网友评论

      本文标题:C++11 使用std::lock_guard和std::mut

      本文链接:https://www.haomeiwen.com/subject/nrlinktx.html