您的位置:首页 > 其它

关于共同生存周期的对象与锁的讨论

2010-03-09 11:48 141 查看
  之前与同学在谈一道smart pointer的面试题,在实现thread safe的时候发现mutex的destroy始终不好解决。问题在于,当你要destroy的mutex之前,必须先unlock这个mutex,而当你unlock这个mutex的同时,你的destroy部分可能不收保护了。与另外一个同学讨论该问题,告之是锁的设计问题。锁不应该和要锁的对象共享一个生存周期。但是,当我们要实现一个对象一个对象的保护的时候,总不能用一个全局锁去管理吧?后来发现,其实,一个对象一个锁,是可以实现完整的保护的。唯一的问题就是destroy这个对象时候。通过增加一个flag方式,我们还是可以保证destroy也能完美的。
  下面是具体的代码:
class myObj
{
public:
   myObj() 
   { 
      pthread_mutex_init(&_mutex);
      _isDestroyed = false;
   }
   ~myObj()
   {
      pthread_mutex_lock(&_mutex);
      _isDestroyed = true;
      ... // Do free memory
      pthread_mutex_unlock(&_mutex);
      pthread_mutex_destroy(&_mutex);
   }
   
   void doSomeThing()
   {
      if (_isDestroyed)
         return;
      pthread_mutex_lock(&_mutex);
      if (_isDestroyed) {
         pthread_mutex_unlock(&_mutex);
         return;
      }
      ... // Access critical fields of this object
      pthread_mutex_unlock(&_mutex); 
   }

private:
   bool _isDestroyed;
   pthread_mutex_t _mutex;
}


其中,我们引入了一个flag, _isDestroyed这个boolean变量。在析构函数里面,我们一旦准备锁住mutex,马上把这个flag设置成true,表示这个对象即将被destroy。那么,其他函数在访问所有临界资源的时候,首先需要看看,这个对象是否马上要被destroy了。如果是,则退出,什么也不要做了;如果不是,再获取锁。析构函数只可能被调用一次,所以在析构函数里面,我们不用对_isDestroyed做判断。但是,我们需要让_isDestroyed的变量是在mutex lock之后才能设置。

这样,即使有线程在析构函数的pthread_mutex_unlock(&_mutex)和pthread_mutex_destroy(&_mutex)之间执行了doSomeThing,也不会影响到临界资源的破坏。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: