天天看點

多線程對構造函數和析構函數的影響

對象構造要做到線程安全,唯一的要求是在構造期間不要洩漏this指針,即

1)不要在構造函數中注冊任何回調函數。

2)不要在構造函數中把this指針傳給跨線程的對象。

3)即便在構造函數的最後一行也不行。

之是以這樣是因為在構造函數執行期間對象還沒有完成初始化,通路這樣的對象會出現難以預料的結果。

對于析構函數,如果是單線程,隻需注意避免空懸指針(對象已經銷毀)和野指針(未初始化的指針)。而多線程時,就需要考慮很多因素了。一個動态建立的對象是否仍有效,光看指針是看不出來的。判斷一個指針是不是合法指針沒有高效的辦法,這是C/C++指針問題的根源。指向對象的原始指針是壞的,尤其當暴露給别的線程時,一個好的解決方法是使用引用計數型智能指針,即boost中的shared_ptr/weak_ptr。shared_ptr是強引用,控制對象的生命期;weak_ptr是若引用,不增加對象的引用次數,但是它知道對象是否還活着。如果對象還活着,那麼它可以提升為有效的share_ptr,如果對象已經死了,提升會失敗,傳回一個空的shared_ptr。shared_ptr是管理共享資源的利器,需要注意避免循環引用,通常的做法是ower持有執行child的shared_ptr,child持有指向owner的weak_ptr。下面以Observer模式為例。

Observable.h

#ifndef OBSERVABLE_H

#define OBSERVABLE_H

#include <boost/weak_ptr.hpp>

#include <vector>

#include <string>

using namespace std;

using namespace boost;

class Observer;

class Observable{

public:

   Observable();

   ~Observable();

   void registe(weak_ptr<Observer>);

   void unregiste(weak_ptr<Observer>);

   void notifyAll();

   void setData(string,string);

private:

   vector<weak_ptr<Observer> > observe;

   string weather;

   string humidity;

};

#endif

Observable.cpp

#include "Observable.h"

#include "Observer.h"  //一定要包含,否則前項申明也不行

Observable::Observable(){

}

Observable::~Observable(){

}

void Observable::registe(weak_ptr<Observer> obs){

   observe.push_back(obs);

}

void Observable::unregiste(weak_ptr<Observer> obs){

   std::vector<weak_ptr<Observer> >::iterator it = observe.begin();

   while(!(*(*it).lock() == *obs.lock())){

      ++it;

   }

  observe.erase(it);

}

void Observable::notifyAll(){

   std::vector<weak_ptr<Observer> >::iterator it = observe.begin();

   while(it != observe.end()){

   shared_ptr<Observer> obj(it->lock());

      if(obj){

         obj->update(weather,humidity);

     ++it;

      }

      else

         it = observe.erase(it);

   }

}

void Observable::setData(string wea,string hum){

   weather = wea;

   humidity = hum;

   notifyAll();

}

Observer.h

#ifndef OBSERVER_H

#define OBSERVER_H

#include <boost/shared_ptr.hpp>

#include <boost/enable_shared_from_this.hpp>

using namespace std;

using namespace boost;

class Observable;

class Observer:public enable_shared_from_this<Observer>{

public:

   Observer(shared_ptr<Observable>);

   void obser(shared_ptr<Observable>);

   bool operator==(const Observer&);

   ~Observer();

   void update(string,string);

private:

   shared_ptr<Observable> subject;

};

#endif

Observer.cpp

#include "Observer.h"

#include "Observable.h"

#include <iostream>

using namespace std;

using namespace boost;

Observer::Observer(shared_ptr<Observable> sub):subject(sub){

}

void Observer::obser(shared_ptr<Observable> s){

   (*s).registe(shared_from_this());

}

Observer::~Observer(){

}

bool Observer::operator==(const Observer& obs){

   return *this == obs;

}

void Observer::update(string wea,string hum){

   cout<<"Weather is "<<wea<<" and Humidity is "<<hum<<"\n";

}

testObser.cpp

#include "Observable.h"

#include "Observer.h"

int main(){

   shared_ptr<Observable> subject(new Observable);

   shared_ptr<Observer> p(new Observer(subject));

   p->obser(subject);

   subject->setData("Fine","Mid");

   subject->setData("Bad","High");

   return 0;

}

這裡需要注意shared_ptr循環引用的情況,此處使用weak_ptr來消除此隐患。

繼續閱讀