当前位置: 首页 > news >正文

【并发编程】线程安全的栈容器

std::stack容器的接口包括 empty(), size(), top(), push(), pop()等。

问题

其原接口在多线程的情况下,会持续很多问题。

例如,在std::stack容器的接口中,在多线程下应用时,empty()和size()的结果是不可信的。因为尽管在某线程调用empty()或size()时,返回值可能是正确的,但是一旦函数返回,其他线程就不再受限,从而能自由地访问栈容器,可能马上会有新元素入栈,或者现有的元素立即出栈,这会使前面线程得到的结果失效。

其次,top()和pop()之间也存在着竞争条件,例如

线程A线程B
if(!s.empty());
if(!s.empty());
 int const value = s.top();
 int const value = s.top();
s.pop()
do_something(value);s.pop()
do_something(value);

假设,当前只有两个线程正在运行,且在两个top()调用之间不存在其他操作,那么栈容器不会被更改,即两个线程会得到相同的值。另外,在top()与pop()的调用之间也没有其他调用,结果栈顶元素被调用了两次,但栈顶的第二个元素却始终没被读取就丢弃了。

解决方法

为了线程安全,在每次操作之前,都加锁

面对第二个问题,将top()和pop()操作合二为一

#include <memory>
#include <mutex>
#include <stack>using namespace std;struct empty_stack :std::exception
{const char* what() const throw();
};template<typename T>
class threadsafe_stack
{
private:stack<T> data;mutable mutex m;public:threadsafe_stack() {};threadsafe_stack(const threadsafe_stack& other){lock_guard<mutex> lock(other.m);data = other.data;}threadsafe_stack& operator=(const threadsafe_stack&) = delete;void push(T new_value){lock_guard<mutex> lock(m);data.push(move(new_value));}shared_ptr<T> pop(){lock_guard<mutex> lock(m);if (data.empty()) throw empty_stack();shared_ptr<T>const res(std::make_shared<T>(data.top()));data.pop();return res;}void pop(T& value){lock_guard<mutex> lock(m);if (data.empty()) throw empty_stack();value = data.top();data.pop();}bool empty() const{lock_guard<mutex> lock(m);return data.empty();}
};

http://www.lryc.cn/news/110573.html

相关文章:

  • ES嵌套查询和普通查询的高亮显示区别
  • Greenplum集群部署
  • 电教智能云数据可视化平台开发电能优化日志实录
  • JSX语法基础总结
  • socker套接字
  • No111.精选前端面试题,享受每天的挑战和学习
  • 【Apollo学习笔记】—— 相机仿真
  • 【数据结构】——线性表的相关习题
  • SpringBoot集成Elasticsearch8.x(8)|(新版本Java API Client的Painless语言脚本script使用)
  • SpringBoot复习:(19)Condition接口和@Conditional注解
  • K8s中的Controller
  • 【MFC】03.常用复杂控件的使用-笔记
  • Autosar诊断实战系列14-NRC优先级解析
  • 《向量数据库指南》——腾讯云向量数据库Tencent Cloud VectorDB产品特性,架构和应用场景
  • xcode 的app工程与ffmpeg 4.4版本的静态库联调,ffmpeg内下的断点无法暂停。
  • 机器学习06 数据准备-(利用 scikit-learn基于Pima Indian数据集作 数据特征选定)
  • 机器学习-特征选择:如何使用Lassco回归精确选择最佳特征?
  • SpringBoot之Actuator基本使用
  • 排序算法(一)
  • Centos虚拟机忘记密码-修改密码
  • Shell 分析服务器日志常用命令
  • mysql8配置binlog日志skip-log-bin,开启、关闭binlog,清理binlog日志文件
  • 机器学习:训练集与测试集分割train_test_split
  • 淘宝API开发(一)简单介绍淘宝API功能接口作用
  • Redis相关面试题
  • 数据库简介
  • 腾讯云国际轻量应用服务器怎么使用呢?
  • arm环境cloudstack在vpc下创建虚拟机失败
  • Linux上安装Keepalived,多台Nginx配置Keepalived(保姆级教程)
  • centos7 ‘xxx‘ is not in the sudoers file...