美文网首页
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