简体   繁体   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";
    }
  }
};

is log_String() {} thread-safe? log_String() {}线程安全的吗? I think that even if many threads call simultaneously log_String() {} this should not be a problem? 我认为即使许多线程同时调用log_String() {}这也不应该成为问题吗? Am i getting this wrong? 我搞错了吗? If i'm wrong possible solution may be to define it private and protect the instantiation of a new object acquiring a new lock? 如果我错了,可能的解决方案可能是将其定义为private并保护获取新锁的新对象的实例化?

log_String() is basically a function, but it is also a constructor. log_String()基本上是一个函数,但它也是一个构造函数。 So in effect its call during object creation means also calling constructors of all member variables (which have constructors), as well as constructors of all the base classes, and constructors of their member variables, recursively. 因此,实际上,它在对象创建期间的调用意味着还递归调用所有成员变量的构造函数(具有构造函数),所有基类的构造函数及其成员变量的构造函数。

So you need to consider all the functions which get called. 因此,您需要考虑所有被调用的函数。 The two member variables, list and m , should have thread safe constructors, since they are from the standard library, and while I didn't check from the standard (draft should be freely downloadable, if you want to check yourself), things would be just crazy if they didn't have thread-safe constructors. 这两个成员变量listm应该具有线程安全的构造函数,因为它们来自标准库,尽管我没有从标准库中进行检查(草稿应该可以免费下载,如果您想检查一下自己的话),如果他们没有线程安全的构造函数,那就疯了。 Then there is no base class, and no code in your constructor. 然后,没有基类,构造函数中也没有代码。

Conclusion, it is thread-safe , because there's nothing in there, which would cause problems "even if many threads call simultaneously log_String()" . 结论, 它是线程安全的 ,因为其中没有任何内容, 即使“许多线程同时调用log_String()” ,也可能导致问题。 No shared data or other shared resources visible, and if there are any shared data hidden in the member variables, they can be trusted to be done safely. 没有可见的共享数据或其他共享资源,并且如果成员变量中隐藏了任何共享数据,则可以信任它们可以安全地完成。

Writing thread-unsafe public constructors could be considered stupid, even evil. 编写线程不安全的公共构造函数可能被认为是愚蠢的,甚至是邪恶的。 Still, if you had member variables or base class from 3rd party libraries, or just of your own types, and you aren't 100% sure of their quality, then it's worth it to stop and think if this kind of stupidity has been done. 不过,如果您有来自第三方库的成员变量或基类,或者只是您自己的类型,并且您不确定其质量100%,那么值得停下来思考一下这种愚蠢的做法是否值得。


An example code which one might plausibly write, especially for debugging purposes, and which would make things thread-unsafe: 示例代码一个看似合理写,尤其是为了调试的目的,并且这将使事情线程安全的:

private:
    static unsigned static_counter;

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

For completeness: Fix for the above code would be to simply use std::atomic<unsigned> for the counter. 为了完整起见:修复以上代码将仅使用std::atomic<unsigned>作为计数器。 More complex cases might require static mutexes (beware if you are using old crappy compilers (at least MSVC2010) which might have unavoidable race conditions with static data). 更复杂的情况可能需要静态互斥体(请注意,如果您使用的是旧的app脚的编译器(至少是MSVC2010),可能会对静态数据产生不可避免的竞争条件)。

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

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