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

有这样一个场景

使用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. tornado-请求与响应

    import tornado.ioloop import tornado.web import tornado.httpserver # 非阻塞 import tornado.options # 提供 ...

  2. 20.Scrapy日常练手

    1.创建爬虫项目: scrapy  startproject tutorial 2.创建 spider cd tutorial scrapy  genspider quotes quotes.tosc ...

  3. eclipse运行程序时报java.lang.OutOfMemoryError: Java heap space内存不足问题

    System.setProperty("webdriver.firefox.bin", "D:\\Mozilla Firefox\\firefox.exe"); ...

  4. leetcode107

    /** * Definition for a binary tree node. * public class TreeNode { * public int val; * public TreeNo ...

  5. linux 安装svn服务器

    一.下载 http://subversion.tigris.org/downloads/subversion-1.6.1.tar.gz http://subversion.tigris.org/dow ...

  6. Linux SWAP 交换分区配置说明(转)

    一.SWAP 说明 1.1 SWAP 概述 当系统的物理内存不够用的时候,就需要将物理内存中的一部分空间释放出来,以供当前运行的程序使用.那些被释放的空间可能来自一些很长时间没有什么操作的程序,这些被 ...

  7. Redis 安装 和 启动

    Redis下载官网 http://download.redis.io/releases/  本人下载了stable版 1:安装步骤 ># wget http://download.redis.i ...

  8. as3 XML类和XMLList类的区别

    一.XML类和XMLList类的区别       AS3.0中,处理XML主要用到两个主类,XML类和XMLList类,这两个类的很多内容是共通的.应该有人会问,XML和XMLList的区别是什么? ...

  9. 基于OpenGL编写一个简易的2D渲染框架-09 重构渲染器-Shader

    Shader 只是进行一些简单的封装,主要功能: 1.编译着色程序 2.绑定 Uniform 数据 3.根据着色程序的顶点属性传递顶点数据到 GPU 着色程序的编译 GLuint Shader::cr ...

  10. input 提交属性 hidden属性

    name名字最好和你后台属性的成员变量对应,否则在参数传递的时候接收不到出现空指针异常.一般表单提交后input会以name的值=value的值的形式传给后台.如:<input type=&qu ...