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())。这样,在不能安全的将元素拷贝出去的情况下,栈中的这个数据还依旧存在,没有丢失。当问题是堆空间不足,应用可能会释放一些内存,然后再进行尝试。

相关推荐
EmbedLinX3 小时前
嵌入式之协议解析
linux·网络·c++·笔记·学习
薛定谔的猫喵喵3 小时前
基于PyQt5的视频答题竞赛系统设计与实现
开发语言·qt·音视频
岱宗夫up3 小时前
Python 数据分析入门
开发语言·python·数据分析
wangjialelele3 小时前
Linux中的进程管理
java·linux·服务器·c语言·c++·个人开发
码界筑梦坊3 小时前
325-基于Python的校园卡消费行为数据可视化分析系统
开发语言·python·信息可视化·django·毕业设计
历程里程碑4 小时前
普通数组----轮转数组
java·数据结构·c++·算法·spring·leetcode·eclipse
多恩Stone4 小时前
【RoPE】Flux 中的 Image Tokenization
开发语言·人工智能·python
李日灐4 小时前
C++进阶必备:红黑树从 0 到 1: 手撕底层,带你搞懂平衡二叉树的平衡逻辑与黑高检验
开发语言·数据结构·c++·后端·面试·红黑树·自平衡二叉搜索树
汉克老师4 小时前
GESP2025年6月认证C++二级( 第一部分选择题(1-8))
c++·循环结构·表达式·分支结构·gesp二级·gesp2级
Risehuxyc4 小时前
备份三个PHP程序
android·开发语言·php