使用智能指针解决多线程下 类的解析冲突问题
有这样一个场景
使用StockFactory记录Stock的信息 容器是map<string,smart_ptr>;
代码如下:
1 #include <functional> 2 #include <memory> 3 #include <string> 4 #include <map> 5 #include <assert.h> 6 #include <mutex> 7 8 using std::string; 9 10 class Stock 11 { 12 public: 13 Stock(const string& name) 14 : name_(name) 15 { 16 printf("Stock[%p] %s ", this, name_.c_str()); 17 } 18 19 ~Stock() 20 { 21 printf("~Stock[%p] %s ", this, name_.c_str()); 22 } 23 24 const string& key() const { return name_; } 25 26 private: 27 string name_; 28 }; 29 30 31 // questionable code 32 class StockFactory 33 { 34 public: 35 36 std::shared_ptr<Stock> get(const string& key) 37 { 38 std::lock_guard<std::mutex> lock(mutex_); 39 std::shared_ptr<Stock>& pStock = stocks_[key]; 40 if (!pStock) 41 { 42 pStock.reset(new Stock(key)); 43 } 44 return pStock; 45 } 46 47 48 private: 49 std::mutex mutex_; 50 std::map<string, std::shared_ptr<Stock> > stocks_; 51 }; 52 53 54 55 int main() 56 { 57 StockFactory sf1; 58 { 59 std::shared_ptr<Stock> s1 = sf1.get("stock1"); 60 } 61 printf("s1 should destruct "); 62 63 return 0; 64 }
运行显示如下
Stock[007E8818] stock1
s1 should destruct
~Stock[007E8818] stock1
没有按照预想的进行析构
说明我们的map容器应该使用弱指针weak_ptr,否则就会出现STOCKFACTOR不析构,STOCK也不会析构的强引用
代码如下
1 #include <functional> 2 #include <memory> 3 #include <string> 4 #include <map> 5 #include <assert.h> 6 #include <mutex> 7 8 using std::string; 9 10 class Stock 11 { 12 public: 13 Stock(const string& name) 14 : name_(name) 15 { 16 printf("Stock[%p] %s ", this, name_.c_str()); 17 } 18 19 ~Stock() 20 { 21 printf("~Stock[%p] %s ", this, name_.c_str()); 22 } 23 24 const string& key() const { return name_; } 25 26 private: 27 string name_; 28 }; 29 30 31 // questionable code 32 class StockFactory 33 { 34 public: 35 std::shared_ptr<Stock> get(const string& key) 36 { 37 std::shared_ptr<Stock> pStock; 38 std::lock_guard<std::mutex> lock(mutex_); 39 std::weak_ptr<Stock>& wkStock = stocks_[key]; 40 pStock = wkStock.lock(); 41 if (!pStock) 42 { 43 pStock.reset(new Stock(key)); 44 wkStock = pStock; 45 } 46 return pStock; 47 } 48 49 private: 50 std::mutex mutex_; 51 std::map<string, std::weak_ptr<Stock> > stocks_; 52 }; 53 54 55 56 int main() 57 { 58 StockFactory sf2; 59 { 60 std::shared_ptr<Stock> s1 = sf2.get("stock2"); 61 } 62 printf("s1 should destruct "); 63 64 return 0; 65 }
运行显示如下
Stock[00468818] stock2
~Stock[00468818] stock2
s1 should destruct
运行情况与我们预想的情况一致 下面的问题就是我们使用的map容器中,当STOCK解析了,map却没有将其智能指针移除
所以在使用智能指针的时候我们要订制析构函数
1 // 11111.cpp : 定义控制台应用程序的入口点。 2 // 3 4 #include "stdafx.h" 5 #include <functional> 6 #include <memory> 7 #include <string> 8 #include <map> 9 #include <assert.h> 10 #include <mutex> 11 12 using std::string; 13 14 class Stock 15 { 16 public: 17 Stock(const string& name) 18 : name_(name) 19 { 20 printf("Stock[%p] %s ", this, name_.c_str()); 21 } 22 23 ~Stock() 24 { 25 printf("~Stock[%p] %s ", this, name_.c_str()); 26 } 27 28 const string& key() const { return name_; } 29 30 private: 31 string name_; 32 }; 33 34 35 class StockFactory 36 { 37 public: 38 39 std::shared_ptr<Stock> get(const string& key) 40 { 41 std::shared_ptr<Stock> pStock; 42 std::lock_guard<std::mutex> lock(mutex_); 43 std::weak_ptr<Stock>& wkStock = stocks_[key]; 44 pStock = wkStock.lock(); 45 if (!pStock) 46 { 47 pStock.reset(new Stock(key), 48 std::bind(&StockFactory::deleteStock, this, std::placeholders::_1)); 49 wkStock = pStock; 50 } 51 return pStock; 52 } 53 54 private: 55 56 void deleteStock(Stock* stock) 57 { 58 printf("deleteStock[%p] ", stock); 59 if (stock) 60 { 61 std::lock_guard<std::mutex> lock(mutex_); 62 stocks_.erase(stock->key()); 63 } 64 delete stock; // sorry, I lied 65 } 66 std::mutex mutex_; 67 std::map<string, std::weak_ptr<Stock> > stocks_; 68 }; 69 70 71 void testLongLifeFactory() 72 { 73 std::shared_ptr<StockFactory> factory(new StockFactory); 74 { 75 std::shared_ptr<Stock> stock = factory->get("NYSE:IBM"); 76 std::shared_ptr<Stock> stock2 = factory->get("NYSE:IBM"); 77 assert(stock == stock2); 78 // stock destructs here 79 } 80 // factory destructs here 81 } 82 83 void testShortLifeFactory() 84 { 85 std::shared_ptr<Stock> stock; 86 { 87 std::shared_ptr<StockFactory> factory(new StockFactory); 88 stock = factory->get("NYSE:IBM"); 89 std::shared_ptr<Stock> stock2 = factory->get("NYSE:IBM"); 90 assert(stock == stock2); 91 // factory destructs here 92 } 93 // stock destructs here 94 } 95 96 97 int main() 98 { 99 StockFactory sf3; 100 { 101 std::shared_ptr<Stock> s3 = sf3.get("stock3"); 102 } 103 printf("s1 should destruct "); 104 105 testLongLifeFactory(); 106 testShortLifeFactory();//此处出错 因为我们BIND函数的时候使用的是this指针 而STOCK析构的时候 FACTORY早已不在 107 108 return 0; 109 }
剩下的视阅读回复量再决定是否继续