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

实现引用计数线程安全的shared_ptr

c++11引入了三个智能指针,用来自动管理内存,使用智能指针可以有效地减少内存泄漏。

其中,shared_ptr是共享智能指针,可以被多次拷贝,拷贝时其内部的引用计数+1,被销毁时引用计数-1,如果引用计数为0,那么释放其所管理的资源

线程安全上,shared_ptr具有如下特点:

  • shared_ptr的引用计数是线程安全的
  • 修改shared_ptr不是线程安全的
  • 读写shared_ptr管理的数据不是线程安全的

具体可以参考:https://zhuanlan.zhihu.com/p/664993437

在网上找到的shared_ptr的手动实现都是线程不安全的,那么如何实现一个引用计数线程安全的shared_ptr呢?

参考:从零简单实现一个线程安全的C++共享指针(shared_ptr)-CSDN博客,本文在这篇博客的基础上增加了验证代码,并指出原有实现一个潜在的bug

#include <iostream>
#include <atomic>
#include <mutex>
#include <thread>
#include <vector>using namespace std;#define N 10000class Counter
{
public:Counter() { count = 1; }void add() {lock_guard<std::mutex> lk(mutex_);count++; }void sub() {lock_guard<std::mutex> lk(mutex_);count--;}int get() {lock_guard<std::mutex> lk(mutex_);return count; }private:int count;std::mutex mutex_;
};template <typename T>
class Sp
{
public:Sp();                           //默认构造函数~Sp();                          //析构函数Sp(T *ptr);                     //参数构造函数Sp(const Sp &obj);              //复制构造函数Sp &operator=(const Sp &obj);   //重载=T *get();                       //得到共享指针指向的类int getcount();                 //得到引用计数器
private:T *my_ptr;                      //共享指针所指向的对象Counter* counter;                   //引用计数器void clear();                   //清理函数
};//默认构造函数,参数为空,构造一个引用计数器
template<typename T>
Sp<T>::Sp()
{my_ptr = nullptr;counter = new Counter();
}//复制构造函数,新的共享指针指向旧的共享指针所指对象
template<typename T>
Sp<T>::Sp(const Sp &obj)
{//将所指对象也变为目标所指的对象my_ptr = obj.my_ptr;//获取引用计数器,使得两个共享指针用一个引用计数器counter = obj.counter;//使这个对象的引用计数器+1counter->add();	
};//重载=
template<typename T>
Sp<T> &Sp<T>::operator=(const Sp&obj)
{//清理当前所引用对象和引用计数器clear();//指向新的对象,并获取目标对象的引用计数器my_ptr = obj.my_ptr;counter = obj.counter;//引用计数器+1counter->add();//返回自己return *this;	
}//创建一个共享指针指向目标类,构造一个新的引用计数器
template<typename T>
Sp<T>::Sp(T *ptr)
{my_ptr = ptr;counter = new Counter();
}//析构函数,出作用域的时候,调用清理函数
template<typename T>
Sp<T>:: ~Sp()
{clear();
}//清理函数,调用时将引用计数器的值减1,若减为0,清理指向的对象内存区域
template<typename T>
void Sp<T>::clear()
{//引用计数器-1counter->sub();//如果引用计数器变为0,清理对象if(0 == counter->get()){// 这里有个bug,如果在此间隙处,有另外一个地方执行了share ptr的copy操作,则会crashif(my_ptr){delete my_ptr;}delete counter;}
}//当前共享指针指向的对象,被几个共享指针所引用
template<typename T>
int Sp<T>::getcount()
{return counter->get();	
};class A{
public:A(){ cout<<"A construct!"<<endl; };~A() { cout<<"A destruct!"<<endl; };
};Sp<A> sp(new A);
std::vector<Sp<A>> vec1(N);
std::vector<Sp<A>> vec2(N);Sp<A> sp1(new A);
Sp<A> sp2(new A);
Sp<A> sp3(new A);void thread_func1() {for(int i = 0; i < N; i++) {vec1[i] = sp;}
}void thread_func2() {for(int i = 0; i < N; i++) {vec2[i] = sp;}
}void test_crash_func1() {sp1 = sp2;
}void test_crash_func2() {sp3 = sp1;
}void test_crash() {for(int i = 0; i < 10 * N; i++) {std::thread t1(test_crash_func1);std::thread t2(test_crash_func2);t1.join();t2.join();}
}int main()
{std::thread t1(thread_func1);std::thread t2(thread_func2);t1.join();t2.join();std::cout<<"the count is:"<<sp.getcount()<<std::endl;test_crash();
}

按理说调用test_crash应该会导致crash才对,但是不知道为什么没有crash

TODO:使用原子操作实现,对比性能

相关文章:

实现引用计数线程安全的shared_ptr

c11引入了三个智能指针&#xff0c;用来自动管理内存&#xff0c;使用智能指针可以有效地减少内存泄漏。 其中&#xff0c;shared_ptr是共享智能指针&#xff0c;可以被多次拷贝&#xff0c;拷贝时其内部的引用计数1&#xff0c;被销毁时引用计数-1&#xff0c;如果引用计数为…...

今日行情明日机会——20250507

指数今天放量上涨&#xff0c;政策层面也释放出重大利好消息~ 上证缺口已补&#xff0c;大盘股表现总体较好 深证60分钟缺口依然未补&#xff0c;等待后续走势~ 2025年5月7日涨停股主要行业方向分析 一、核心主线方向 军工&#xff08;政策催化地缘驱动&#xff09; • 涨停…...

配置Hadoop集群-测试使用

&#xff08;一&#xff09;上传小文件 上传文件的时候&#xff0c;我们传一个大一点的&#xff08;>128M&#xff09;&#xff0c;再传一个小一点的。对于大一点的文件&#xff0c;我们要去看看它是否会按128M为单位去拆分这个大文件&#xff0c;而拆分成大文件之后&#…...

MEGA3:分子进化遗传学分析和序列比对集成软件

李升伟 摘译 摘要 在分子进化和群体遗传学的理论基础稳固确立后&#xff0c;比较DNA和蛋白质序列分析在重建物种和多基因家族的进化历史、估计分子进化速率以及推断塑造基因和基因组进化的性质和程度方面发挥了核心作用。随着高通量测序技术和新颖的统计及计算方法的发展&…...

21. LangChain金融领域:合同审查与风险预警自动化

引言&#xff1a;当AI成为24小时不眠的法律顾问 2025年某商业银行的智能合同系统&#xff0c;将百万级合同审查时间从平均3周缩短至9分钟&#xff0c;风险条款识别准确率达98.7%。本文将基于LangChain的金融法律框架&#xff0c;详解如何构建合规、精准、可追溯的智能风控体系…...

7D-AI系列:模型微调之mlx-lm

大模型的出现&#xff0c;导致信息量太大&#xff0c;只有静心动手操作&#xff0c;才能得到真理。 文章目录 环境要求安装示例mlx-lm微调工具参数准备数据集下载模型微调模型合并模型验证结果验证微调前的模型验证微调后的模型 环境要求 macbook pro m系列芯片mlx环境已安装 …...

数据可视化:php+echarts实现数据可视化(包含echart安装引入)

一、实现效果 实现动态时间,多列柱状图,单列柱状图,普通表格,表格动画等效果 二、实现 1、动态时间显示 通过php获取当前时间 设置计时器来动态显示时间秒数 <!-- 时间动画 --> <script>// 动态更新时间中的秒数function updateTime() {const now = new D…...

《Python星球日记》 第47天:聚类与KMeans

名人说&#xff1a;路漫漫其修远兮&#xff0c;吾将上下而求索。—— 屈原《离骚》 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 专栏&#xff1a;《Python星球日记》&#xff0c;限时特价订阅中ing 目录 一、聚类与…...

linux(centos)联网情况下部署

nginx部署 1.linux(centos)联网情况下部署 1.下载nginx所需依赖 # 安装开发工具组&#xff08;若未安装&#xff09; sudo yum groupinstall "Development Tools"# 安装 OpenSSL 开发包 sudo yum install openssl-devel# 安装 PCRE 开发包 sudo yum install pcre-…...

Kubernetes生产级资源管理实战:从QoS策略到OOM防御体系

一、资源限制的本质&#xff1a;不是成本控制&#xff0c;而是稳定性保障 当集群中某个节点的内存耗尽时&#xff0c;Kubernetes会像冷酷的交通警察一样&#xff0c;根据Pod的"优先级证件"&#xff08;QoS类别&#xff09;决定哪些Pod需要被驱逐。这种机制直接关系到…...

gcc的使用

gcc 是 GNU Compiler Collection&#xff08;GNU 编译器套件&#xff09;的缩写&#xff0c;是 GNU 项目开发的编程语言编译器集合&#xff0c;支持多种编程语言&#xff08;如 C、C、Objective-C、Fortran、Ada 等&#xff09;。以下是关于 gcc 的核心信息&#xff1a; 1. 主要…...

聊一聊Qwen3思考模式实现以及背后原理探讨

Qwen3思考模式切换实现 硬开关 我们先通过官方的示例代码来体验一下&#xff0c;如何实现在思考模式和非思考模式之间切换 通过tokenizer.apply_chat_template的enable_thinking参数来实现 默认情况下&#xff0c;Qwen3 启用了思考功能&#xff0c;类似于 QwQ-32B。这意味着…...

spark行动算子

在 Apache Spark 中&#xff0c;行动算子&#xff08;Action&#xff09;用于触发对 RDD 的实际计算&#xff0c;并将结果返回给驱动程序&#xff08;Driver&#xff09;或保存到外部存储系统中。与转换算子&#xff08;Transformation&#xff09;不同&#xff0c;行动算子会立…...

电商双十一美妆数据分析(代码)

import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns import jieba # 数据读取 df pd.read_csv(双十一_淘宝美妆数据.csv) # 数据清洗 # 处理重复值 data df.drop_duplicates(inplaceFalse) data data.reset_index(in…...

STM32裸机开发问题汇总

一、代码编写 1. keil中某个文件无法修改 keil中某个文件无法修改&#xff0c;不能输入_keil5 h文件无法修改-CSDN博客 2.编译报错declaration may not appear after executable statement in block STM32常见错误error: #268: declaration may not appear after executabl…...

C语言复习笔记--自定义类型

今天我们来复习一下自定义类型.自定义类型大概分为结构体,枚举,联合体,数组这几种.数组在之前就介绍过.今天我们来看下其他三种. 结构体 首先来看结构体. 结构体类型的声明 之前在操作符的地方简单认识过结构体.下面我们回顾一下. 结构体回顾 结构是⼀些值的集合&#xff0c;这…...

做 iOS 调试时,我尝试了 5 款抓包工具

日常做开发的人&#xff0c;特别是和客户端接口打交道的同学&#xff0c;应该对“抓包”这件事不陌生。 调试登录流程、分析接口格式、排查错误返回、分析网络性能、甚至研究第三方 App 的数据通信……说到底&#xff0c;都绕不开“抓 HTTPS 包”这一步。 而这一步&#xff0…...

html css js网页制作成品——HTML+CSS珠海网页设计网页设计(4页)附源码

目录 一、&#x1f468;‍&#x1f393;网站题目 二、✍️网站描述 三、&#x1f4da;网站介绍 四、&#x1f310;网站效果 五、&#x1fa93; 代码实现 &#x1f9f1;HTML 六、&#x1f947; 如何让学习不再盲目 七、&#x1f381;更多干货 一、&#x1f468;‍&#x1f…...

FID和IS的区别

&#x1f4ca; 生成模型评估&#xff1a;你选 IS 还是 FID&#xff1f; 在评估 GAN、Diffusion 等图像生成模型时&#xff0c;两个最常被提到的指标是&#xff1a; &#x1f539;IS (Inception Score) &#x1f539;FID (Frchet Inception Distance) &#x1f9e0; Inception…...

前端三大件--HTML

引言 在互联网的世界里&#xff0c;每一个绚丽多彩的网页背后&#xff0c;都离不开 HTML 的支撑。HTML&#xff08;Hyper Text Markup Language&#xff0c;超文本标记语言&#xff09;作为网页开发的基础语言&#xff0c;就像是搭建高楼大厦的砖块&#xff0c;是所有 Web 开发…...

Node.js 的 child_process 模块详解

Node.js 的 child_process 模块提供了创建子进程的能力,使 Node.js 应用能够执行系统命令、运行其他程序或脚本。这个模块非常强大,可以帮助我们实现很多复杂的功能。 1. exec - 执行 shell 命令 exec 方法用于执行 shell 命令,并缓冲任何产生的输出。 特点 创建 shell 来…...

日常知识点之随手问题整理(虚函数 虚函数表 继承的使用场景)

新来的同事提到一个虚函数解耦头文件的问题&#xff0c;就想起来对虚函数进行一些回顾。 他的问题是&#xff0c;通过纯虚函数&#xff0c;如何实现不包含头文件即可真正调用到子类的实际接口。 》这里肯定是不合理的&#xff0c;需要一个中间管理类&#xff0c;对纯虚函数和相…...

【软件设计师:数据结构】2.数据结构基础(二)

一、树 树是n(n≥0)个结点的有限集合,n=0时称为空树,在任一非空树中 ● 有且仅有一个称为根的结点。 ● 其余的结点可分为m(m≥0)个互不相交的子集T1,T2…,Tm,其中每个子集本身又是一棵树,并称其为根结点的子树。 1、树的基本概念 ● 双亲和孩子 ● 兄弟:具有相同双…...

Python训练营打卡——DAY18(2025.5.7)

目录 一、基于聚类进一步推断类型 1. 聚类分析 2. 簇的总结与定义 二、作业 1. 聚类分析 2. 簇的总结与定义 3. 模型效果提升 一、基于聚类进一步推断类型 选用昨天kmeans得到的效果进行聚类&#xff0c;进而推断出每个簇的实际含义。 1. 聚类分析 # 先运行之前预处理…...

初学Python爬虫

文章目录 前言一、 爬虫的初识1.1 什么是爬虫1.2 爬虫的核心1.3 爬虫的用途1.4 爬虫分类1.5 爬虫带来的风险1.6. 反爬手段1.7 爬虫网络请求1.8 爬虫基本流程 二、urllib库初识2.1 http和https协议2.2 编码解码的使用2.3 urllib的基本使用2.4 一个类型六个方法2.5 下载网页数据2…...

【CSS】Grid 的 auto-fill 和 auto-fit 内容自适应

CSS Grid 的 auto-fill 和 auto-fit /* 父元素 */ .grid {display: grid;/* 定义「网格容器」里有多少列&#xff0c;以及每列的宽度 *//* repeat 是个「重复函数」&#xff0c;表示后面的模式会被重复多次 *//* auto-fit 是一个特殊值&#xff0c;自动根据容器宽度&#xff…...

绕线机的制作与研究

绕线机的制作与研究 摘要 本文详细阐述了绕线机的制作过程,涵盖从设计规划到实际制作的各个环节。通过对绕线机工作原理的深入分析,确定了关键技术参数,并依此完成机械结构与控制系统的设计。在制作阶段,运用多种加工工艺完成零件制造与设备组装。经测试,自制绕线机性能…...

引用的使用

引用的语法 作用&#xff1a;起别名 引用的本质是指针常量 数据类型 &别名原名&#xff1b; 引用必须要初始化 引用一旦初始化&#xff0c;不能修改 不能返回局部变量的引用 引用做形参 #include<iostream> #include<string> using namespace std; //通过引用…...

css animation 动画属性

animation // 要绑定的关键帧规则名称 animation-name: slidein;// 定义动画完成一个周期所需的时间&#xff0c;秒或毫秒 animation-duration: 3s;// 定义动画速度曲线 animation-timing-function: ease;// 定义动画开始前的延迟时间 animation-delay: 1s;// 定义动画播放次数…...

Nacos源码—Nacos集群高可用分析(二)

4.集群节点的健康状态变动时的数据同步 (1)Nacos后台管理的集群管理模块介绍 在集群管理模块下&#xff0c;可以看到每个节点的状态和元数据。节点IP就是节点的IP地址以及端口&#xff0c;节点状态就是标识当前节点是否可用&#xff0c;节点元数据就是相关的Raft信息。 其中节点…...

SRAM详解

一、SRAM基础原理 定义与结构 SRAM&#xff08;Static Random-Access Memory&#xff0c;静态随机存取存储器&#xff09;是一种基于触发器&#xff08;Flip-Flop&#xff09;结构的易失性内存&#xff0c;通过交叉耦合的反相器&#xff08;6晶体管&#xff0c;6T单元&#xff…...

JavaWeb:MySQL进阶

多表设计 一对多&#xff08;多对一&#xff09; 外键 一对一 多对多 多表查询 内连接 外连接 子查询 -- 查询员工表 select * from emp;-- 查询部门表 select * from dept;-- 查询员工和部门 select * from emp, dept; -- 笛卡尔积select * from emp, dept where emp.dept_i…...

Golang 接口 vs Rust Trait:一场关于抽象的哲学对话

一、引言 在现代编程语言中&#xff0c;接口&#xff08;Interface&#xff09; 和 Trait 是实现多态和抽象行为的关键机制。它们允许我们定义行为契约&#xff0c;让不同的类型共享相同的语义接口&#xff0c;从而提升代码的复用性和扩展性。 Go 和 Rust 分别代表了两种截然…...

智算中心的搭建标准

智算中心的搭建标准主要涉及以下几个方面&#xff1a; 开放标准&#xff1a; 硬件与软件开放&#xff1a;从硬件到软件、从芯片到架构&#xff0c;都应采用开放、标准的技术。例如&#xff0c;硬件支持如 OCP、ODCC、Open19 等开放社区标准&#xff0c;软件采用如 OpenStack、K…...

商汤科技前端面试题及参考答案

有没有配置过 webpack,讲一下 webpack 热更新原理,能否自己实现一些插件? Webpack 是一个用于现代 JavaScript 应用程序的静态模块打包工具。在实际项目中,经常会对其进行配置,以满足项目的各种需求,比如处理不同类型的文件、优化代码、配置开发服务器等。 Webpack 热更…...

windows下docker的使用

找了个docker教程 Windows Docker 安装 | 菜鸟教程Windows Docker 安装 Docker 并非是一个通用的容器工具&#xff0c;它依赖于已存在并运行的 Linux 内核环境。Docker 实质上是在已经运行的 Linux 下制造了一个隔离的文件环境&#xff0c;因此它执行的效率几乎等同于所部署的…...

AI日报 · 2025年5月07日|谷歌发布 Gemini 2.5 Pro 预览版 (I/O 版本),大幅提升编码与视频理解能力

1、谷歌发布 Gemini 2.5 Pro 预览版 (I/O 版本)&#xff0c;大幅提升编码与视频理解能力 谷歌于5月6日提前发布 Gemini 2.5 Pro 预览版 (I/O 版本)&#xff0c;为开发者带来更强编码能力&#xff0c;尤其优化了前端与UI开发、代码转换及智能体工作流构建&#xff0c;并在WebDe…...

Redis 8.0 正式版发布,新特性很强!

就在前两天&#xff0c;Redis 8.0 正式版 (GA) 来了&#xff01;这并不是一次简单的更新&#xff0c;Redis 8.0 不仅带来了性能上的进一步提升&#xff0c;还带来一些实用的新特性与功能增强。并且&#xff0c;最重要的是拥抱 AGPLv3 重归开源&#xff01; 下面&#xff0c;简单…...

MySQL核心机制:日志系统、锁机制与事务管理的深度剖析

一.介绍 MySQL作为世界上最流行的开源关系型数据库之一&#xff0c;其强大的事务处理能力和高并发支持使其在各种复杂应用场景中得到广泛应用。MySQL的核心机制包括日志系统、锁机制和事务管理&#xff0c;这些机制共同确保了数据库的ACID特性&#xff0c;为应用程序提供了可靠…...

Mybatis标签使用 -association 绑定对象,collection 绑定集合

注意 association标签中的 select , column 属性使用 collection 标签中的 ofType 属性使用 Data public class Tours implements Serializable {private static final long serialVersionUID 1L;private Integer touId;private String tourName;private Integer guideId;pri…...

IBM BAW(原BPM升级版)使用教程Toolkit介绍

本部分为“IBM BAW&#xff08;原BPM升级版&#xff09;使用教程系列”内容的补充。 一、系统Toolkit 在 IBM Business Automation Workflow (BAW) 中&#xff0c;System Toolkit 是一组预先定义和配置好的工具、功能和组件&#xff0c;旨在帮助流程设计者和开发人员快速构建…...

排列组合算法:解锁数据世界的魔法钥匙

在 C 算法的奇幻世界里&#xff0c;排列和组合算法就像是两把神奇的魔法钥匙&#xff0c;能够帮我们解锁数据世界中各种复杂问题的大门。今天&#xff0c;作为 C 算法小白的我&#xff0c;就带大家一起走进排列和组合算法的奇妙天地。 排列算法&#xff1a;创造所有可能的顺序…...

LVGL -meter的应用

1 meter介绍 lv_meter 是 LVGL v8 引入的一种图形控件&#xff0c;用于创建仪表盘样式的用户界面元素&#xff0c;它可以模拟像速度表、电压表、温度表这类模拟表盘。它通过可视化刻度、指针、颜色弧线等来展示数值信息&#xff0c;是一种非常直观的数据展示控件。 1.1 核心特…...

MCP学习

一、MCP基础理论与核心概念 1.1 协议定义与设计目标 MCP&#xff08;Model Context Protocol&#xff09;是Anthropic公司于2024年11月开源的标准化协议&#xff0c;旨在解决大型语言模型&#xff08;LLM&#xff09;与外部工具、数据源之间的动态交互问题。其核心目标包括&…...

软件工程(三):模块的内聚模型

模块内聚的7种类型&#xff08;从低到高&#xff09; 等级类型描述示例1️⃣ 最低偶然性内聚&#xff08;Coincidental Cohesion&#xff09;模块内部的各功能毫无关系&#xff0c;随机拼凑一个模块中既有文件读写&#xff0c;又有图像压缩、还处理用户登录2️⃣逻辑性内聚&am…...

Java中字符转数字的原理解析 - 为什么char x - ‘0‘能得到对应数字

前言 在Java编程中&#xff0c;我们经常需要将字符形式的数字转换为实际的数值。有很多方法可以实现这一转换&#xff0c;比如使用Integer.parseInt()或Character.getNumericValue()等方法。但有一种简便且高效的方式是直接使用char - 0运算&#xff0c;本文将详细解析这种方法…...

View的事件分发机制

&#xff08;一&#xff09;为什么要有事件分发机制 安卓界面上面的View的层级结构是树形的&#xff0c;可能出现多个View重叠在一起的现象&#xff08;如下图&#xff09;&#xff0c;当我们点击的地方为多个View重叠的区域时&#xff0c;这个点击事件应该给谁呢&#xff1f;为…...

【C++】类和对象【下】

目录 一、再探构造函数1、测试题 二、类型转换三、static成员1. 静态成员变量2. 静态成员函数 四、友元五、内部类六、匿名对象七、对象拷贝时的编译器优化 个人主页<—请点击 C专栏<—请点击 一、再探构造函数 之前我们实现构造函数时&#xff0c;初始化成员变量主要使…...

【JS逆向基础】并发爬虫

前言&#xff1a;所谓并发编程是指在一台处理器上“同时”处理多个任务。并发是在同一实体上的多个事件。强调多个事件在同一时间间隔发生。 1&#xff0c;进程、线程以及协程 【1】进程概念 我们都知道计算机的核心是CPU&#xff0c;它承担了所有的计算任务;而操作系统是计算…...

Android组件化 -> 基础组件进行Application,Activity生命周期分发

在lib_common基础组件模块创建上下文持有类&#xff0c;生命周期派发类 object AppContextProvider {private lateinit var application: Applicationprivate var currentActivityRef: WeakReference<Activity>? null// 应用生命周期监听器列表private val appLifecyc…...