• C++11:基于std::queue和std::mutex构建一个线程安全的队列


    C++11:基于std::queue和std::mutex构建一个线程安全的队列

    C++中的模板std::queue提供了一个队列容器,但这个容器并不是线程安全的,如果在多线程环境下使用队列,它是不能直接拿来用的。
    基于它做一个线程安全的队列也并不复杂。基本的原理就是用std::mutext信号量对std::queue进行访问控制,以保证任何一个线程都是独占式访问,下面是完整的代码。

    /*
     * threadsafe_queue.h
     *
     *  Created on: 2016年7月26日
     *      Author: guyadong
     */
    
    #ifndef COMMON_SOURCE_CPP_THREADSAFE_QUEUE_H_
    #define COMMON_SOURCE_CPP_THREADSAFE_QUEUE_H_
    #include <queue>
    #include <mutex>
    #include <condition_variable>
    #include <initializer_list>
    namespace gdface {
    inline namespace mt{
    /*
     * 线程安全队列
     * T为队列元素类型
     * 因为有std::mutex和std::condition_variable类成员,所以此类不支持复制构造函数也不支持赋值操作符(=)
     * */
    template<typename T>
    class threadsafe_queue{
    private:
        // data_queue访问信号量
        mutable std::mutex mut;
        mutable std::condition_variable data_cond;
        using queue_type = std::queue<T>;
        queue_type data_queue;
    public:
        using value_type= typename queue_type::value_type;
        using container_type = typename queue_type::container_type;
        threadsafe_queue()=default;
        threadsafe_queue(const threadsafe_queue&)=delete;
        threadsafe_queue& operator=(const threadsafe_queue&)=delete;
        /*
         * 使用迭代器为参数的构造函数,适用所有容器对象
         * */
        template<typename _InputIterator>
        threadsafe_queue(_InputIterator first, _InputIterator last){
            for(auto itor=first;itor!=last;++itor){
                data_queue.push(*itor);
            }
        }
        explicit threadsafe_queue(const container_type &c):data_queue(c){}
        /*
         * 使用初始化列表为参数的构造函数
         * */
        threadsafe_queue(std::initializer_list<value_type> list):threadsafe_queue(list.begin(),list.end()){
        }
        /*
         * 将元素加入队列
         * */
        void push(const value_type &new_value){
            std::lock_guard<std::mutex>lk(mut);
            data_queue.push(std::move(new_value));
            data_cond.notify_one();
        }
        /*
         * 从队列中弹出一个元素,如果队列为空就阻塞
         * */
        value_type wait_and_pop(){
            std::unique_lock<std::mutex>lk(mut);
            data_cond.wait(lk,[this]{return !this->data_queue.empty();});
            auto value=std::move(data_queue.front());
            data_queue.pop();
            return value;
        }
        /*
         * 从队列中弹出一个元素,如果队列为空返回false
         * */
        bool try_pop(value_type& value){
            std::lock_guard<std::mutex>lk(mut);
            if(data_queue.empty())
                return false;
            value=std::move(data_queue.front());
            data_queue.pop();
            return true;
        }
        /*
         * 返回队列是否为空
         * */
        auto empty() const->decltype(data_queue.empty()) {
            std::lock_guard<std::mutex>lk(mut);
            return data_queue.empty();
        }
        /*
         * 返回队列中元素数个
         * */
        auto size() const->decltype(data_queue.size()){
            std::lock_guard<std::mutex>lk(mut);
            return data_queue.size();
        }
    }; /* threadsafe_queue */
    }/* namespace mt */
    }/* namespace gdface */
    #endif /* COMMON_SOURCE_CPP_THREADSAFE_QUEUE_H_ */

    这里只实现了阻塞式的pop函数wait_and_pop,你也可以根据自己的需要对代码进行适当的改造,以符合自己的需求。 
    (C++11风格代码,在VS2015和gcc5.2.0下编译通过)

    因为有std::mutex和std::condition_variable类成员,所以此类不支持复制构造函数也不支持赋值操作符(=)

  • 相关阅读:
    Balance的数学思想构造辅助函数
    1663. Smallest String With A Given Numeric Value (M)
    1680. Concatenation of Consecutive Binary Numbers (M)
    1631. Path With Minimum Effort (M)
    1437. Check If All 1's Are at Least Length K Places Away (E)
    1329. Sort the Matrix Diagonally (M)
    1657. Determine if Two Strings Are Close (M)
    1673. Find the Most Competitive Subsequence (M)
    1641. Count Sorted Vowel Strings (M)
    1679. Max Number of K-Sum Pairs (M)
  • 原文地址:https://www.cnblogs.com/leijiangtao/p/12064110.html
Copyright © 2020-2023  润新知