使用智能指针解决多线程下 类的解析冲突问题

有这样一个场景

使用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多线程服务端编程>学习记录的更多相关文章

  1. Python灰帽子:黑客与逆向工程师的Python编程之道|百度网盘免费下载|新手黑客入门

    百度网盘免费下载:Python灰帽子:黑客与逆向工程师的Python编程之道 提取码:tgpg 目录  · · · · · · 第1章 搭建开发环境 11.1 操作系统要求 11.2 获取和安装Pyt ...

  2. Python灰帽子:黑客与逆向工程师的Python编程之道PDF高清完整版免费下载|百度云盘

    百度云盘免费下载:Python灰帽子:黑客与逆向工程师的Python编程之道PDF高清完整版免费下载 提取码:8nki 目录  · · · · · · 第1章 搭建开发环境 11.1 操作系统要求 1 ...

  3. 《灰帽Python-黑客和逆向工程师的Python编程》学习记录

    ctypes是Python语言的一个外部库,提供和C语言兼容的数据类型,可以很方便的调用C DLL中的函数. 操作环境:CentOS6.5 Python版本:2.66 ctypes是强大的,强大到本书 ...

  4. 【Python灰帽子--黑客与逆向工程师的Python编程之道】我的学习笔记,过程.(持续更新HOT)

    我的学习笔记---python灰帽子 世界让我遍体鳞伤,但伤口长出的却是翅膀. -------------------------------------------- 前言 本书是由知名安全机构Im ...

  5. python核心编程学习记录之映射和集合类型

    字典是python里唯一的映射类型

  6. python核心编程学习记录之Python对象

    比较符号如<,>,=比较的是对象的值 如果要比较对象本身要用is,is not repr()的功能与''所做的事情是一样的 Python不支持的类型有char,byte,指针,short, ...

  7. python核心编程学习记录之基础知识

    虽然对python的基础知识有所了解,但是为了更深入的学习,要对python的各种经典书籍进行学习 第一章介绍python的优缺点,略过 第二章介绍python起步,第三章介绍python基础,仅记录 ...

  8. Python大神成长之路: 第一次学习记录

    一.Python发展史 二.Python2 or 3 博主选择了Python3. 从官网下载Python  www.python.org Windows安装python3.5.python2.7.安装 ...

  9. 流畅的python第十九章元编程学习记录

    在 Python 中,数据的属性和处理数据的方法统称属性(attribute).其实,方法只是可调用的属性.除了这二者之外,我们还可以创建特性(property),在不改变类接口的前提下,使用存取方法 ...

  10. 流畅的python第四章文本和字节序列学习记录

    字符问题 把码位转化成字节序列的过程是编码,把字节序列转化成码位的过程是解码 把unicode字符串当成人类可读的文本,码位当成机器可读的, 将字节序列编程人类可读是解码,把字符串编码成字节序列是编码 ...

随机推荐

  1. 使用amaze ui模板全过程

    amaze ui基于gulp构建,所以现在安装gulp需要的环境,gulp使用npm安装,npm基于node.js 所以一切从node.js开始 1 下载对应的node.js 打开 https://n ...

  2. 4. java乱码处理

    //返回到jsp页面 //request.setCharacterEncoding("utf-8"); //response.setContentType("text/h ...

  3. Node + H5 + WebSocket + Koa2 实现简单的多人聊天

    服务器代码  ( 依赖于 koa2,  koa-websocket ) /* 实例化外部依赖 */ let Koa = require("koa2"); let WebSocket ...

  4. leetcode258

    public class Solution { public int AddDigits(int num) { var str = num.ToString(); ; foreach (var c i ...

  5. vue -本地服务配置

    1.httpd.conf # # This is the main Apache HTTP server configuration file. It contains the # configura ...

  6. vue - iview UI组件的col标签报错 x-invalid-end-tag

    https://blog.csdn.net/xiao199306/article/details/80430087

  7. Centos7搭建pptp一键安装脚本

    废话不多说,先上脚本地址:Centos7一键pptp 使用: wget http://files.cnblogs.com/files/wangbin/CentOS7-pptp-host1plus.sh ...

  8. 设计模式学习笔记(1)Iterator

    Iterator 模式 public interface Iterator { public boolean hasNext(); public Object next(); } public int ...

  9. 迷你MVVM框架 avalonjs 学习教程15、属性监听与模块通信

    avalon的ViewModel对象从其内部EventManager里继承了三个方法,$watch.$unwatch.$fire三个方法,它们就是我们本节的主题. 词如其名,非常直白,一看就知道做什么 ...

  10. HTML meta 文本 格式排版 链接图表 列表 表单 frame后台布局实例

    meta标签 content属性必须和http-equiv或者name属性一起使用 http-equiv属性,就是http当量,用于和服务器发送数据前的提交交互使用.(另层含义这个当量在浏览器和服务器 ...