【问题标题】:Does the wrapper class for a thread safe object also need to be made thread-safe?线程安全对象的包装类是否也需要成为线程安全的?
【发布时间】:2016-11-14 08:24:31
【问题描述】:

[我没有找到任何令人满意的答案,因此发布了一个问题。]

假设我有一个线程安全的 C++ 类“ThreadSafeClass”。现在,我在它上面写了一个包装器“MyWrapper”。 MyWrapper 没有任何其他数据成员。我在这里有几个疑问:

  1. 此包装类的各个方法是否也需要由互斥锁保护以使其线程安全?或者可以假设因为底层对象是线程安全的所以没有必要?
  2. 如果上面 的答案是否定的(包装器中不需要互斥锁),那么请考虑以下问题:假设对唯一底层对象的访问始终是线程安全的,我们不会通过任何互斥锁来保护包装器类。现在假设 1 个线程在包装器对象的析构函数中,而另一个线程正在访问其成员函数(假设包装器类没有任何互斥锁来避免这种情况)。线程安全对象是否可能已被一个线程销毁,然后另一个线程尝试访问它?我知道这听起来有点奇怪,很可能我遗漏了一些东西,但这取决于上面 的答案。

    class MyWrapper {
    private:
        ThreadSafeClass _ts_obj;
    public:
        void foo()
        {
            _ts_obj.do_something();
        }
    };
    

【问题讨论】:

  • 在这种情况下,您不需要额外的mutex
  • 直接使用相同的类对象或通过包含该对象的包装器间接调用方法同样安全。一个线程位于包装器的析构函数中的概念类似于一个线程位于对象的析构函数中,因为它也会被破坏。让一个线程在一个类对象上运行而另一个线程正在破坏它不是一个好主意。
  • 我认为您需要定义“线程安全对象”一词的含义。
  • 您在#2 中提出的观点听起来像是错误的设计。您应该有某种确定性的生命周期管理,以便在 MyWrapper 的实例超出范围之前在线程上 join..
  • @Galik 我的意思是假设该对象属于一个在设计时考虑到适当线程同步的类。在我的特定用例中,它是 log4cplus::Logger 类,它是线程安全的,我打算在它上面写一个包装器。

标签: c++ multithreading thread-safety


【解决方案1】:
  1. 不,在给定的场景中,您不必使用额外的互斥锁来保护包装类

  2. 当多个线程使用同一个对象时,您应该非常小心地管理对象的生命周期,这样一个线程就不能在其他线程访问该对象时销毁该对象。最简单的方法是在线程中使用shared_ptr<Wrapper> 智能指针来访问数据。这是线程安全的引用计数智能指针,一旦对象没有被任何线程引用,就会销毁它。

【讨论】:

    【解决方案2】:
    1. 不,您不需要额外的互斥层。
    2. 如果您在两个线程之间共享对象,则需要将对象作为引用/指针传递。在这种情况下,线程析构函数只会清理引用/指针,但拥有底层的删除对象,所以一切正常。如果您将对象作为副本传递,那么一切都很好。

    编辑: 当然,如果您强制删除指针下的对象,您将遇到分段错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-09-29
      • 2016-05-08
      • 2010-11-06
      • 2013-12-07
      • 2011-08-13
      • 1970-01-01
      相关资源
      最近更新 更多