Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/155.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/three.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 这样做安全吗+;单例第一实例创建?_C++_Multithreading - Fatal编程技术网

C++ 这样做安全吗+;单例第一实例创建?

C++ 这样做安全吗+;单例第一实例创建?,c++,multithreading,C++,Multithreading,据我所知,如果Singleton::instance()是在不同的线程中调用的,那么如果两个调用都引用实际实例的第一个构造,则可能会出现一些问题 因此,如果我将第一个Singleton::instance()调用移动到程序的最开始,在那里甚至没有创建其他线程,那么现在这是线程安全的吗 当然,它的所有成员变量在使用时都受到互斥保护。是的,在可以保证只有一个线程存在的情况下执行初始实例化可以明显地保护它不受其他导致争用条件的线程的影响 不过,它感觉并不十分健壮。至少,在该区域贴上警告注释 因此,如果

据我所知,如果Singleton::instance()是在不同的线程中调用的,那么如果两个调用都引用实际实例的第一个构造,则可能会出现一些问题

因此,如果我将第一个Singleton::instance()调用移动到程序的最开始,在那里甚至没有创建其他线程,那么现在这是线程安全的吗


当然,它的所有成员变量在使用时都受到互斥保护。

是的,在可以保证只有一个线程存在的情况下执行初始实例化可以明显地保护它不受其他导致争用条件的线程的影响

不过,它感觉并不十分健壮。至少,在该区域贴上警告注释

因此,如果我将第一个Singleton::instance()调用移动到程序的最开始,在那里甚至没有创建其他线程,那么现在这是线程安全的吗

是的,但是这个元素不在
单例
的设计中,如果是这样的话,它可能会更加健壮


您通常可以使用
静态
方法中的
静态
存储在文件范围或功能范围内分配它。验证编译器是否在其周围生成排除,或者在其中添加您自己的互斥体。

这样您就不需要对单例实例进行延迟初始化了


如果您确实需要它,那么您可以在构建它时使用互斥来保护单例实例。

这可能会让您看到线程安全的单例,而这是多么容易。

和以前一样,如果您要求在任何线程启动之前创建它,那么它不是非常健壮


不过值得注意的是,如果您使用C++11进行编译,那么按照Brian所说的(静态存储+静态方法)进行操作可以保证线程安全。对于任何以前的版本,您都需要一个互斥锁,并且会遇到我在分享的链接中提到的注意事项。

请记住不要将其放在标题中。
如果将实现放在头中,则它可能会在使用它的每个编译单元中生成。这意味着它不会是单身


也不要在静态库中编译它。如果代码链接并合并到多个非静态库中,这也可能导致多个实例。

如果尚未创建其他线程,并且您在创建这些线程之前进行了移动,我不认为在任何新创建的多线程环境中,使用已经创建的单实例会出现问题


单线程模式在多线程环境中的主要线程安全问题是如何防止不同线程创建两个或多个“单线程”实例。我已经在“多线程环境”一节中描述了这个场景。

线程安全单例安装的常见模式是Scott Meyer(请举个例子)。与单例一样,您的第一项工作应该是认真考虑是否真的需要它。我想说,至少90%的时候它是一种净损失,这不仅增加了它自身的复杂性,而且至少在不让客户端代码变得更复杂的情况下也是如此。