多线程安全的stack类

您所在的位置:网站首页 lock的实现类 多线程安全的stack类

多线程安全的stack类

2023-05-25 16:36| 来源: 网络整理| 查看: 265

声明:本文参考自《C++并发编程实战(第二版)》

       本文试图根据书中的代码在力所能及范围内实现一个stack类,虽然底层用了现成的stack,比较丑陋(请忽略)

        在实现的类中功能自认为不够全面,后面写TinySTL项目的时候再模板化和追加功能吧.

5-17 更新,追加swap方法的类内实现和友元,改写push方法,追加try_pop和wait_and_pop方法

// 实现一个多线程安全的栈 // 用一个不会抛出异常的类防止异常扩散 struct empty_stack :std::exception { const char ch = 'n'; const char* what() const throw() { return &ch; } }; template class threadsafe_stack; template void swap(threadsafe_stack& l, threadsafe_stack& r); template bool operator==(threadsafe_stack&, threadsafe_stack&); template class threadsafe_stack { private: stackdata; mutable std::mutex m; mutable std::shared_mutex sm; std::condition_variable dt; public: threadsafe_stack() {} threadsafe_stack(const threadsafe_stack& other) { std::lock_guardlck(other.m); data = other.data; } // 对于是否在取数据时加锁,我的评价是,服从比较的逻辑 // 如果强调比较时的瞬时性,建议在取数据之前就加锁 std::mutex& get_mutex() { return this->m; } stack& get_data() { return this->data; } // 取消掉等号赋值,将这个功能内化到构造函数 threadsafe_stack& operator=(const threadsafe_stack&) = delete; bool empty() const { std::lock_guardlck(m); return data.empty(); } void swap(threadsafe_stack& other) noexcept { // c++11 or c++14 //lock(this->m, other.m); //std::lock_guardlck1(other.m, std::adopt_lock); //std::lock_guardlck2(this->m, std::adopt_lock); // c++17 std::scoped_lock guard(this->m, other.m); this->data.swap(other.data); } friend void swap(threadsafe_stack& l, threadsafe_stack& r) { // c++11 or c++14 //std::lock(l.get_mutex(), r.get_mutex()); //std::lock_guardlck1(l.get_mutex(), std::adopt_lock); //std::lock_guardlck2(l.get_mutex(), std::adopt_lock); // c++17 std::scoped_lock guard(l.get_mutex(), r.get_mutex()); std::swap(l.get_data(), r.get_data()); } // top 和 size 两个函数都不是多线程安全的,应该在具体的上下文情境中加锁使用 // 但是函数功能本身并没有问题 /* _NODISCARD unsigned int size() { lock_guardlck(m); return data.size(); } */ T top() { std::lock_guardlck(sm); if (data.empty()) throw empty_stack(); return data.top(); } std::shared_ptrtop(T) { std::lock_guardlck(sm); if (data.empty()) throw empty_stack(); const std::shared_ptrres(std::make_shared(data.top())); return res; } void push(const T& val) { std::lock_guardlck(m); data.push(val); dt.notify_one(); } void push(T&& val) { std::lock_guardlck(m); data.push(std::move(val)); dt.notify_one(); } // 提供几个重载版本 std::shared_ptrpop() { std::lock_guardlck(m); if (data.empty()) throw empty_stack(); const std::shared_ptr res(std::make_shared(data.top())); data.pop(); return res; } void pop(T& value) { std::lock_guardlck(m); if (data.empty()) throw empty_stack(); value = data.top(); data.pop(); } bool try_pop(T& value) { std::lock_guardlck(m); if (data.empty()) return false; value = data.top(); data.pop(); return true; } std::shared_ptrtry_pop() { std::lock_guardlck(m); if (data.empty()) return std::shared_ptr(); std::shared_ptrres(std::make_shared(data.top())); data.pop(); return res; } void wait_and_pop(T& value) { std::unique_locklck(m); dt.wait(lck, [this] {return !data.empty(); }); value = data.top(); data.pop(); } std::shared_ptrwait_and_pop() { std::unique_locklck(m); dt.wait(lck, [this] {return !data.empty(); }); std::shared_ptrres(std::make_shared(data.top())); data.pop(); return res; } bool operator==(const threadsafe_stack& oth) { // c++11 or c++14 //std::lock(l.get_mutex(), r.get_mutex()); //std::lock_guardlck1(l.get_mutex(), std::adopt_lock); //std::lock_guardlck2(l.get_mutex(), std::adopt_lock); // c++17 std::scoped_lock guard(m, oth.m); return data == oth.data; } friend bool operator==(threadsafe_stack& l, threadsafe_stack& r) { // c++11 or c++14 //std::lock(l.get_mutex(), r.get_mutex()); //std::lock_guardlck1(l.get_mutex(), std::adopt_lock); //std::lock_guardlck2(l.get_mutex(), std::adopt_lock); // c++17 std::scoped_lock guard(l.get_mutex(), r.get_mutex()); return l.get_data() == r.get_data(); } };

测试代码如下:

void oper(threadsafe_stack& s) { for (int i = 0; i < 100; i++) { s.push(i); cout


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3