C++用锁实现线程安全的stack容器

cpp 复制代码
#include <exception>
#include <memory>
#include <mutex>
#include <stack>
struct empty_stack: std::exception
{
  const char* what() const throw() {
    return "empty stack!";
  };
};
template<typename T>
class threadsafe_stack
{
private:
  std::stack<T> data;
  mutable std::mutex m;
public:
  threadsafe_stack()
    : data(std::stack<T>()){}
  threadsafe_stack(const threadsafe_stack& other)
  {
    std::lock_guard<std::mutex> lock(other.m);
    data = other.data; // 1 在构造函数体中的执行拷贝
  }
  threadsafe_stack& operator=(const threadsafe_stack&) = delete;
  void push(T new_value)
  {
    std::lock_guard<std::mutex> lock(m);
    data.push(new_value);
  }
  std::shared_ptr<T> pop()
  {
    std::lock_guard<std::mutex> lock(m);
    if(data.empty()) throw empty_stack(); // 在调用pop前,检查栈是否为空
    std::shared_ptr<T> const res(std::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();
  }
};

为什么STL设计时top和pop没组合在一起?

假设有一个stack<vector>,vector是一个动态容器,当你拷贝一个vetcor,标准库会从堆上分配很多内存来完成这次拷贝。当这个系统处在重度负荷,或有严重的资源限制的情况下,这种内存分配就会失败,所以vector的拷贝构造函数可能会抛出一个std::bad_alloc异常。当vector中存有大量元素时,这种情况发生的可能性更大。当pop()函数返回"弹出值"时(也就是从栈中将这个值移除),会有一个潜在的问题:这个值被返回到调用函数的时候,栈才被改变;但当拷贝数据的时候,调用函数抛出一个异常会怎么样? 如果事情真的发生了,要弹出的数据将会丢失;它的确从栈上移出了,但是拷贝失败了!std::stack的设计人员将这个操作分为两部分:先获取顶部元素(top()),然后从栈中移除(pop())。这样,在不能安全的将元素拷贝出去的情况下,栈中的这个数据还依旧存在,没有丢失。当问题是堆空间不足,应用可能会释放一些内存,然后再进行尝试。

相关推荐
Tony Bai14 小时前
高并发后端:坚守 Go,还是拥抱 Rust?
开发语言·后端·golang·rust
wjs202414 小时前
Swift 类型转换
开发语言
秃了也弱了。15 小时前
python实现定时任务:schedule库、APScheduler库
开发语言·python
weixin_4407305015 小时前
java数组整理笔记
java·开发语言·笔记
Thera77715 小时前
状态机(State Machine)详解:原理、优缺点与 C++ 实战示例
开发语言·c++
linux开发之路15 小时前
C++高性能日志库开发实践
c++·c++项目·后端开发·c++新特性·c++校招
niucloud-admin16 小时前
java服务端——controller控制器
java·开发语言
刻BITTER16 小时前
在TRAE 上安装PlatformIO
c++·单片机·嵌入式硬件·arduino
永远都不秃头的程序员(互关)16 小时前
C++动态数组实战:从手写到vector优化
c++·算法
夏幻灵16 小时前
JAVA基础:基本数据类型和引用数据类型
java·开发语言