【问题标题】:How can I destroy a shared object safely in a multi-threaded program?如何在多线程程序中安全地销毁共享对象?
【发布时间】:2013-01-15 01:39:24
【问题描述】:

我设计了一些类。是这样的:

  1. ClientEntity 类可以有多个实例。
  2. ClientEntity对象创建时不会被修改,所以我不使用互斥体。
  3. ClientEntity 对象可以在不同线程之间访问。
  4. ClientEntity 对象在收到一些退出命令时会被销毁。
  5. ClientEntity 对象可能会被某些线程访问。

我怎样才能安全地销毁这个对象?

class ClientEntity
{
public:
    conference_info & conf_info (){return conf_info_;}
    void conf_info(const conference_info &ci){conf_info_ = ci;}

    user_info & usr_info(){return usr_info_;}
    void usr_info(const user_info &ui){usr_info_ = ui;}

private:
    web_conf_info *wci_;
    user_info usr_info_;
    conference_info conf_info_;

    // .....
};

class user_info
{
public:
    user_info & operator = (const user_info &ui)
    {   
        if (this != &ui){
            user_id = ui.user_id;
            user_name = ui.user_name;
            user_role = ui.user_role;
        }   

        return *this;
    }   
public:
    int user_id;
    int user_role;
    std::string user_name;
};


class conference_info
{
public:
    conference_info & operator = (const conference_info &conf)
    {   
        if (this != &conf){
            conf_id = conf.conf_id;
            dtsip_list = conf.dtsip_list;
            ctsip_list = conf.ctsip_list;
        }   

        return *this;
    }
public:
    int conf_id;
    std::list<std::string> dtsip_list;
    std::list<std::string> ctsip_list;
};

【问题讨论】:

  • 根据您发布的使用案例的定义,“安全”销毁对象的唯一方法是确保该特定实例不会/不会再次发生使用。 IE。在你吃之前,没有一根线在馅饼里有突出的手指。
  • shared_ptr 是你的朋友。或者,如果对象不是太大且不可变(即不能按您所说的那样修改),请复制它们。

标签: c++


【解决方案1】:

确定您可以(或不能)删除共享对象的典型方法是使用引用计数 - 通过使用“共享指针”或作为类本身中您自己的逻辑的一部分。您必须有某种由客户端代码使用的函数来表示“我想使用这个对象”,这会增加引用计数。当客户端完成时,它会调用“我不再对这个对象感兴趣”并且引用计数倒计时。如果引用计数变为零(并且由于其他原因不需要该对象),则可以将其删除。

【讨论】:

  • 您还有其他解决方案吗?
  • 我建议的解决方案在哪些特定方面不好?它对于 Linux 操作系统中的虚拟内存页面来说已经足够好了,并且通常用于图形解决方案(例如 OpenGL 中的纹理和表面等)。
【解决方案2】:

我建议在创建ClientEntity 对象时,您应该确保它正确地由另一个对象拥有,比如一个全局对象,并且当全局对象被销毁时,删除ClientEntity

当然你可以在多个线程之间随时删除ClientEntity,但是当你试图删除ClientEntity时,使用像临界区这样的同步对象。

访问ClientEntity的其他线程也应该使用临界区等,以防止对象在使用时被删除。

【讨论】:

    【解决方案3】:

    我使用了自己的类来进行引用计数。而且我搜了一下,发现这个可以用:

    Example to use shared_ptr?

    http://www.boost.org/doc/libs/1_52_0/libs/smart_ptr/shared_ptr.htm

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-05-24
      • 1970-01-01
      • 2018-03-31
      • 2018-12-08
      • 2011-11-13
      • 2011-08-02
      • 1970-01-01
      相关资源
      最近更新 更多