C++并发编程实战学习笔记

这篇笔记探讨了C++中多线程开发的实践,特别是如何使用互斥量实现线程安全。文章强调了保护共享数据时的常见错误,如不应将受保护数据传递到互斥锁作用域外。此外,还介绍了线程安全的堆栈实现,包括基本版本和改进版,以避免拷贝构造异常,并确保线程安全。
摘要由CSDN通过智能技术生成

本笔记仅供个人复习所用!!!!

很感谢原作者Anthony Williams,为我提供了一条C++多线程开发的学习捷径,本书中提供了很多关于多线程开发的问题解决方案,是一本好书!

用代码(互斥量mutex)保护共享数据常见错误

  1. 切勿将受保护数据传递到互斥锁作用域之外
  2. 切勿将受保护的数据以参数的形式传递到用户函数中去

线程安全问题-拷贝构造异常(内存分配失败)

  • 传入一个引用
    通过引用来获取想要的值

    缺点:

    • 需要临时构造一个实例,从时间和资源的角度看不划算

    • 需要可赋值的存储类型,因为要通过给传入的引用赋值来获取数据,很多用户自定义的类型可能都不支持赋值操作

  • 无异常抛出的拷贝构造函数或移动构造函数

  • 返回指向数据的指针

    优势:
    自由拷贝,不会发异常

    缺点:
    指针的内存分配管理繁琐(new&&delete),解决方案:使用 std::share_ptr能很好的避免内存泄漏

  • 上述解决方案混合使用

线程安全的堆栈代码实现:

    #include<exception>
    #include<memory>//For std::shared_ptr<>
    struct empty_stack: std::exception{
        constchar* what()constthrow();
    };

    template<typename T>
    class threadsafe_stack{
        public:
        threadsafe_stack();
        threadsafe_stack(const threadsafe_stack&);
        threadsafe_stack& operator=(const threadsafe_stack&)=delete//删除赋值操作
        void push(T new_value);
        std::shared_ptr<T> pop();
        void pop(T& value);
        bool empty()const;//当stack为空时抛出异常
    };

**削减接口可以获得最大限度的安全与数据控制(五个操作->三个操作)**

线程安全的堆栈内部操作实现:

    #include <exception>
    #inlcude <mutex>
    #include <stack>
    #include <memory>
    struct empty_stack:std::exception{
        constchar* what() constthrow{
            return "empty stack!";
        }
    }

    template <typename T>
    class threadsafe_stack{
        private:
        std::stack<T> data;
        mutable std::mutex m;
        public:
        threadsafe_stack():data(stack<T>()){};
        threadsafe_stack(const threadsafe_stack& other){
            std::lock_guard<std::mutex>lock(other.m);//给other对象加锁,保证赋值过程中数据的安全
            data=other.data;
        }
        threadsafe_stack operator=(const threadsafe_stack&)=delete;
        void push(T new_value){
            std::lock_guard<std::mutex>lock(m);
            data.push(new_value);
        }
        std::share_ptr pop(){
            std::lock_guard<std::mutex>lock(m);
            if(data.empty())
                throw empty_stack();
            std::share_ptr<T>const res(make_shared<T>(data.top()));
            data.pop();
            return res;
        }
        void pop(T& value){
            std::lock_guard<std::mutex>lock(m);
            if(data.empty())
                throw empty_stack();
            value=data.top();
            data.pop();
        bool empty()const{
            std::lock_guard<std::mutex>lock(m);
            return data.empty();
        }
        }
    };

线程安全的堆栈(改进版)

    #ifndef THRAEDSAFE_STACK_HPP
    #define THRAEDSAFE_STACK_HPP
    
    #include <mutex>
    #include <condition_variable>
    #include <stack>
    #include <memory>
    
    template<typename T>
    class threadsafe_stack
    {
    private:
        mutable std::mutex mut;
        std::stack<T> data_stack;
        std::condition_variable data_cond;
    public:
        threadsafe_stack()
        {}
        threadsafe_stack(threadsafe_stack const& other)
        {
            std::lock_guard<std::mutex> lk(other.mut);
            data_stack=other.data_stack;
        }
    
        void push(T new_value)
        {
            std::lock_guard<std::mutex> lk(mut);
            data_stack.push(new_value);
            data_cond.notify_one();
        }
    
        void wait_and_pop(T& value)//等待pop返回引用版
        {
            std::unique_lock<std::mutex> lk(mut);
            data_cond.wait(lk,[this]{return !data_stack.empty();});
            value=data_stack.top();
            data_queue.pop();
        }
    
        std::shared_ptr<T> wait_and_pop()//等待pop返回智能指针版
        {
            std::unique_lock<std::mutex> lk(mut);
            data_cond.wait(lk,[this]{return !data_stack.empty();});
            std::shared_ptr<T> res(std::make_shared<T>(data_stack.top()));
            data_queue.pop();
            return res;
        }
    
        bool try_pop(T& value)//尝试pop返回引用版
        {
            std::lock_guard<std::mutex> lk(mut);
            if(data_stack.empty())
                return false;
            value=data_stack.top();
            data_stack.pop();
            return true;
        }
    
        std::shared_ptr<T> try_pop()//尝试pop返回智能指针版
        {
            std::lock_guard<std::mutex> lk(mut);
            if(data_stack.empty())
                return std::shared_ptr<T>();
            std::shared_ptr<T> res(std::make_shared<T>(data_stack.top()));
            data_stack.pop();
            return res;
        }
    
        bool empty() const
        {
            std::lock_guard<std::mutex> lk(mut);
            return data_stack.empty();
        }
    };
    
    #endif
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值