繁体   English   中英

C ++中的默认构造函数是线程安全的吗?

[英]Is the default constructor thread-safe in C++?

class log_String {
  //These are private!
  std::vector<std::string> list;
  std::mutex m;
  log_String& operator=(const log_String &source); //Operatore assegnazione
  log_String(const log_String &source);

public:
  log_String() {}; // <---- is this thread_safe?

  void add(std::string string) {
    std::lock_guard<std::mutex> l(m);
    list.push_back(string);
  }

  void printFile(std::string file) {
    std::lock_guard<std::mutex> l(m);
    std::ofstream myfile;

    myfile.open(file);
    for (auto iterator = list.begin(); iterator != list.end(); ++iterator) {
        myfile << *iterator << "\n";
    }
  }
};

log_String() {}线程安全的吗? 我认为即使许多线程同时调用log_String() {}这也不应该成为问题吗? 我搞错了吗? 如果我错了,可能的解决方案可能是将其定义为private并保护获取新锁的新对象的实例化?

log_String()基本上是一个函数,但它也是一个构造函数。 因此,实际上,它在对象创建期间的调用意味着还递归调用所有成员变量的构造函数(具有构造函数),所有基类的构造函数及其成员变量的构造函数。

因此,您需要考虑所有被调用的函数。 这两个成员变量listm应该具有线程安全的构造函数,因为它们来自标准库,尽管我没有从标准库中进行检查(草稿应该可以免费下载,如果您想检查一下自己的话),如果他们没有线程安全的构造函数,那就疯了。 然后,没有基类,构造函数中也没有代码。

结论, 它是线程安全的 ,因为其中没有任何内容, 即使“许多线程同时调用log_String()” ,也可能导致问题。 没有可见的共享数据或其他共享资源,并且如果成员变量中隐藏了任何共享数据,则可以信任它们可以安全地完成。

编写线程不安全的公共构造函数可能被认为是愚蠢的,甚至是邪恶的。 不过,如果您有来自第三方库的成员变量或基类,或者只是您自己的类型,并且您不确定其质量100%,那么值得停下来思考一下这种愚蠢的做法是否值得。


示例代码一个看似合理写,尤其是为了调试的目的,并且这将使事情线程安全的:

private:
    static unsigned static_counter;

public:
    log_String() {
        ++static_counter; // not atomic operation! potential data race!
    };

为了完整起见:修复以上代码将仅使用std::atomic<unsigned>作为计数器。 更复杂的情况可能需要静态互斥体(请注意,如果您使用的是旧的app脚的编译器(至少是MSVC2010),可能会对静态数据产生不可避免的竞争条件)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM