代码之家  ›  专栏  ›  技术社区  ›  aJ.

析构函数应该是线程安全的吗?

  •  15
  • aJ.  · 技术社区  · 17 年前

    MyClass::~MyClass()
    {
       EnterCriticalSection(&cs);
    
    //Access Data Members, **NO Global** members are being accessed here
    
    
      LeaveCriticalSection(&cs);
    }
    

    我想知道有没有可能保护毁灭者?

    考虑一个场景:

    1. Thread1 - About to execute any of the member function which uses critical section
    2. Thread2-  About to execute destructor.
    

    这是一个设计问题吗?

    8 回复  |  直到 17 年前
        1
  •  37
  •   Mehrdad Afshari    17 年前

    在使用对象时不能调用 . 如果你在处理这种情况, 它需要一个根本性的解决方案 全球的 计数器)。

        2
  •  5
  •   JaredPar    17 年前

    即使您成功地用关键部分保护析构函数,当另一个线程开始执行函数的其余部分时会发生什么?它将对一个已删除的对象执行此操作,该对象(取决于它的分配位置)将是垃圾内存或简单的无效对象。

    您需要修改代码以确保对象在仍在使用时不会被破坏。

        3
  •  4
  •   Jimmy J    17 年前

    如果要访问全局变量,可能需要线程安全,是的

    我的“Window”类将自己添加到构造函数中的“knownWindows”列表中,并在析构函数中删除自己。“knownWindows”需要是线程安全的,这样它们在执行时都会锁定互斥锁。

    另一方面,如果析构函数只访问被销毁对象的成员,则会出现设计问题。

        4
  •  4
  •   David Rodríguez - dribeas    17 年前

    class PeriodicThread : public ACE_Task_Base
    {
    public:
       PeriodicThread() : exit_( false ), mutex_()
       {
       }
       ~PeriodicThread()
       {
          mutex_.acquire();
          exit_ = true;
          mutex_.release();
          wait(); // wait for running thread to exit
       }
       int svc()
       {
          mutex_.acquire();
          while ( !exit_ ) { 
             mutex_.release();
             // perform periodic operation
             mutex_.acquire();
          }
          mutex_.release();
       }
    private:
       bool exit_;
       ACE_Thread_Mutex mutex_;
    };
    

    在这段代码中,析构函数必须使用线程安全技术来保证对象在线程运行之前不会被销毁 svc() 出口。

        5
  •  3
  •   anon anon    17 年前

        6
  •  0
  •   nobody    17 年前

    不会有什么不同的。如您所说,如果调用顺序颠倒,那么您正在对一个已破坏的对象调用一个成员函数,这将失败。同步无法修复该逻辑错误(对于初学者来说,成员函数调用将尝试获取已破坏的锁对象)。

        7
  •  0
  •   Vijay Angelo    17 年前

    我支持尼尔·巴特沃斯的评论。当然,负责删除和访问myclass的实体应该对此进行检查。

    这种同步实际上将从创建MyClass类型的对象的那一刻开始。

        8
  •  0
  •   Matthew    16 年前

    无全球 成员在这里被访问“所以我猜不会。只有创建对象的线程才应该销毁它,那么您会从其他线程保护它吗?

    例子:

    • main()创建一个对象
      • 对象A包含对象B
          • 对象C创建一个访问对象a和B的线程
          • 对象C的析构函数运行,等待其线程完成
        • 对象B的析构函数运行
      • 对象A的析构函数运行
    • main()返回

    对象A和B的析构函数根本不需要考虑线程,而对象C的析构函数只需要实现一些通信机制(例如,等待事件)和它选择自己创建的线程。

        9
  •  0
  •   lumpidu    5 年前

    通常,一个类的公共成员改变了一个关键部分,可以从不同的线程访问该部分,应该锁定这个关键部分。但物体的破坏是物体状态的最终改变 包括…在内 关键部分。

    所以,如果有异步操作在进行,在进入对象的这个临界状态时,销毁肯定应该等到那个临界部分再次离开。一种方法是在析构函数中使用锁。当然,这无助于保证以后不会再错误地访问对象本身。

    但这种技术可以用于同步。在异步结束时销毁对象。关键部位的操作。

    推荐文章