<Linux多线程服务端编程>学习记录
使用智能指针解决多线程下 类的解析冲突问题
有这样一个场景
使用StockFactory记录Stock的信息 容器是map<string,smart_ptr>;
代码如下:
#include <functional>
#include <memory>
#include <string>
#include <map>
#include <assert.h>
#include <mutex> using std::string; class Stock
{
public:
Stock(const string& name)
: name_(name)
{
printf("Stock[%p] %s\n", this, name_.c_str());
} ~Stock()
{
printf("~Stock[%p] %s\n", this, name_.c_str());
} const string& key() const { return name_; } private:
string name_;
}; // questionable code
class StockFactory
{
public: std::shared_ptr<Stock> get(const string& key)
{
std::lock_guard<std::mutex> lock(mutex_);
std::shared_ptr<Stock>& pStock = stocks_[key];
if (!pStock)
{
pStock.reset(new Stock(key));
}
return pStock;
} private:
std::mutex mutex_;
std::map<string, std::shared_ptr<Stock> > stocks_;
}; int main()
{
StockFactory sf1;
{
std::shared_ptr<Stock> s1 = sf1.get("stock1");
}
printf("s1 should destruct\n"); return ;
}
cpp1
运行显示如下
Stock[007E8818] stock1
s1 should destruct
~Stock[007E8818] stock1
没有按照预想的进行析构

说明我们的map容器应该使用弱指针weak_ptr,否则就会出现STOCKFACTOR不析构,STOCK也不会析构的强引用
代码如下
#include <functional>
#include <memory>
#include <string>
#include <map>
#include <assert.h>
#include <mutex> using std::string; class Stock
{
public:
Stock(const string& name)
: name_(name)
{
printf("Stock[%p] %s\n", this, name_.c_str());
} ~Stock()
{
printf("~Stock[%p] %s\n", this, name_.c_str());
} const string& key() const { return name_; } private:
string name_;
}; // questionable code
class StockFactory
{
public:
std::shared_ptr<Stock> get(const string& key)
{
std::shared_ptr<Stock> pStock;
std::lock_guard<std::mutex> lock(mutex_);
std::weak_ptr<Stock>& wkStock = stocks_[key];
pStock = wkStock.lock();
if (!pStock)
{
pStock.reset(new Stock(key));
wkStock = pStock;
}
return pStock;
} private:
std::mutex mutex_;
std::map<string, std::weak_ptr<Stock> > stocks_;
}; int main()
{
StockFactory sf2;
{
std::shared_ptr<Stock> s1 = sf2.get("stock2");
}
printf("s1 should destruct\n"); return ;
}
cpp2
运行显示如下
Stock[00468818] stock2
~Stock[00468818] stock2
s1 should destruct

运行情况与我们预想的情况一致 下面的问题就是我们使用的map容器中,当STOCK解析了,map却没有将其智能指针移除
所以在使用智能指针的时候我们要订制析构函数
// 11111.cpp : 定义控制台应用程序的入口点。
// #include "stdafx.h"
#include <functional>
#include <memory>
#include <string>
#include <map>
#include <assert.h>
#include <mutex> using std::string; class Stock
{
public:
Stock(const string& name)
: name_(name)
{
printf("Stock[%p] %s\n", this, name_.c_str());
} ~Stock()
{
printf("~Stock[%p] %s\n", this, name_.c_str());
} const string& key() const { return name_; } private:
string name_;
}; class StockFactory
{
public: std::shared_ptr<Stock> get(const string& key)
{
std::shared_ptr<Stock> pStock;
std::lock_guard<std::mutex> lock(mutex_);
std::weak_ptr<Stock>& wkStock = stocks_[key];
pStock = wkStock.lock();
if (!pStock)
{
pStock.reset(new Stock(key),
std::bind(&StockFactory::deleteStock, this, std::placeholders::_1));
wkStock = pStock;
}
return pStock;
} private: void deleteStock(Stock* stock)
{
printf("deleteStock[%p]\n", stock);
if (stock)
{
std::lock_guard<std::mutex> lock(mutex_);
stocks_.erase(stock->key());
}
delete stock; // sorry, I lied
}
std::mutex mutex_;
std::map<string, std::weak_ptr<Stock> > stocks_;
}; void testLongLifeFactory()
{
std::shared_ptr<StockFactory> factory(new StockFactory);
{
std::shared_ptr<Stock> stock = factory->get("NYSE:IBM");
std::shared_ptr<Stock> stock2 = factory->get("NYSE:IBM");
assert(stock == stock2);
// stock destructs here
}
// factory destructs here
} void testShortLifeFactory()
{
std::shared_ptr<Stock> stock;
{
std::shared_ptr<StockFactory> factory(new StockFactory);
stock = factory->get("NYSE:IBM");
std::shared_ptr<Stock> stock2 = factory->get("NYSE:IBM");
assert(stock == stock2);
// factory destructs here
}
// stock destructs here
} int main()
{
StockFactory sf3;
{
std::shared_ptr<Stock> s3 = sf3.get("stock3");
}
printf("s1 should destruct\n"); testLongLifeFactory();
testShortLifeFactory();//此处出错 因为我们BIND函数的时候使用的是this指针 而STOCK析构的时候 FACTORY早已不在 return ;
}
剩下的视阅读回复量再决定是否继续
<Linux多线程服务端编程>学习记录的更多相关文章
- Python灰帽子:黑客与逆向工程师的Python编程之道|百度网盘免费下载|新手黑客入门
百度网盘免费下载:Python灰帽子:黑客与逆向工程师的Python编程之道 提取码:tgpg 目录 · · · · · · 第1章 搭建开发环境 11.1 操作系统要求 11.2 获取和安装Pyt ...
- Python灰帽子:黑客与逆向工程师的Python编程之道PDF高清完整版免费下载|百度云盘
百度云盘免费下载:Python灰帽子:黑客与逆向工程师的Python编程之道PDF高清完整版免费下载 提取码:8nki 目录 · · · · · · 第1章 搭建开发环境 11.1 操作系统要求 1 ...
- 《灰帽Python-黑客和逆向工程师的Python编程》学习记录
ctypes是Python语言的一个外部库,提供和C语言兼容的数据类型,可以很方便的调用C DLL中的函数. 操作环境:CentOS6.5 Python版本:2.66 ctypes是强大的,强大到本书 ...
- 【Python灰帽子--黑客与逆向工程师的Python编程之道】我的学习笔记,过程.(持续更新HOT)
我的学习笔记---python灰帽子 世界让我遍体鳞伤,但伤口长出的却是翅膀. -------------------------------------------- 前言 本书是由知名安全机构Im ...
- python核心编程学习记录之映射和集合类型
字典是python里唯一的映射类型
- python核心编程学习记录之Python对象
比较符号如<,>,=比较的是对象的值 如果要比较对象本身要用is,is not repr()的功能与''所做的事情是一样的 Python不支持的类型有char,byte,指针,short, ...
- python核心编程学习记录之基础知识
虽然对python的基础知识有所了解,但是为了更深入的学习,要对python的各种经典书籍进行学习 第一章介绍python的优缺点,略过 第二章介绍python起步,第三章介绍python基础,仅记录 ...
- Python大神成长之路: 第一次学习记录
一.Python发展史 二.Python2 or 3 博主选择了Python3. 从官网下载Python www.python.org Windows安装python3.5.python2.7.安装 ...
- 流畅的python第十九章元编程学习记录
在 Python 中,数据的属性和处理数据的方法统称属性(attribute).其实,方法只是可调用的属性.除了这二者之外,我们还可以创建特性(property),在不改变类接口的前提下,使用存取方法 ...
- 流畅的python第四章文本和字节序列学习记录
字符问题 把码位转化成字节序列的过程是编码,把字节序列转化成码位的过程是解码 把unicode字符串当成人类可读的文本,码位当成机器可读的, 将字节序列编程人类可读是解码,把字符串编码成字节序列是编码 ...
随机推荐
- 返回标签数据示例 (PHP)
标签接口函数 获取标签数据 array uc_tag_get(string tagname [, array nums]) 函数参数 参数 含义 string tagname 标签名称 array n ...
- JavaScript判断浏览器及其版本信息
通过window.navigator来判断: function getBrowserInfo(){ var Info = {}; var str = window.navigator.userAgen ...
- DevExpress.XtraEditors.Groupcontrol 中创建按钮
1. 添加引用: Imports DevExpress.XtraEditors.ButtonsPanelControl 2. 添加按钮语句: GroupControl1.CustomHeaderBut ...
- Java工具类实现校验公民身份证的有效性
转自:https://www.oschina.net/code/snippet_1859292_39120 1 package com.tg.user.controller; import java. ...
- 机器学习入门-随机森林温度预测-增加样本数据 1.sns.pairplot(画出两个关系的散点图) 2.MAE(平均绝对误差) 3.MAPE(准确率指标)
在上一个博客中,我们构建了随机森林温度预测的基础模型,并且研究了特征重要性. 在这个博客中,我们将从两方面来研究数据对预测结果的影响 第一方面:特征不变,只增加样本的数据 第二方面:增加特征数,增加样 ...
- UI5-文档-4.13-Margins and Paddings
我们的应用程序内容仍然粘在信箱的角落里.要微调布局,可以向上一步添加的控件添加空白和填充. 我们将使用SAPUI5提供的标准类,而不是手工向控件添加CSS.这些类负责一致的分级步骤.从左到右的支持和响 ...
- .Net 常用开发工具
,net常用开发工具 LinqPad使用 LinqPad连接Oracle 使用 LINQPad 将linq转换为 lambda表达式 或者 SQL语句 LINQPad 4 初次使用心得 一.双击 二. ...
- 使用sql获取primary key名称
使用sql获取mysql主键名称: 方法1: 这种方法返回一行数据,如果只是需要主键的名称,可以使用方法2. SHOW KEYS FROM <table_name> WHERE Key_n ...
- tnsping 命令解析
C:\Users\nowhill>tnsping jljcz Oracle Net 工具(命令)tnsping,是一个OSI会话层的工具,它用来: 1)验证名字解析(name resolutio ...
- Dotfuscator Professional Edition获取代码发布和混淆代码
1 Dotfuscator Professional Edition 4.9 破解版 下载地址:http://www.pc0359.cn/downinfo/39815.html 备份地址:C:\D\9 ...