Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/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++记录器。然而,由于众所周知,著名的双重检查锁定方法不再是线程安全的,我想知道我是否应该:_C++_Design Patterns_Singleton_Logging - Fatal编程技术网

简单C++;使用单例模式的记录器 由于使用单模式模式实现日志记录的泛滥实例,我在程序中编写了一个简单的C++记录器。然而,由于众所周知,著名的双重检查锁定方法不再是线程安全的,我想知道我是否应该:

简单C++;使用单例模式的记录器 由于使用单模式模式实现日志记录的泛滥实例,我在程序中编写了一个简单的C++记录器。然而,由于众所周知,著名的双重检查锁定方法不再是线程安全的,我想知道我是否应该:,c++,design-patterns,singleton,logging,C++,Design Patterns,Singleton,Logging,1) 忘了在这种情况下使用单例模式吗 2) 即使不安全,是否继续使用双重检查锁定 3) 对其公共接口的每次访问都使用昂贵的纯同步锁定方法 有什么建议吗?使用Meyers Singleton。如果您使用的是gcc,那么至少初始化是线程安全的 class Singleton{ Singleton(){ //This is threadsafe in gcc, no mutex required } static Singleton * instance(){ s

1) 忘了在这种情况下使用单例模式吗

2) 即使不安全,是否继续使用双重检查锁定

3) 对其公共接口的每次访问都使用昂贵的纯同步锁定方法


有什么建议吗?

使用Meyers Singleton。如果您使用的是gcc,那么至少初始化是线程安全的

class Singleton{
   Singleton(){
    //This is threadsafe in gcc, no mutex required
   }
   static Singleton * instance(){
      static Singleton myinstance;
      return &myinstance;
   }
};

gcc保护静态局部构造,除非您禁用-fno threadsafe statics,我最近写过关于这一点的文章,在有线程的应用程序中,我更喜欢使用initialize()函数和断言来确保initialize()在第一个实例()之前使用。从主线程调用initialize()。我不认为惰性实例化是单例的关键特性,特别是对于记录器


虽然Arkaitz的答案更为优雅,但我的答案避免了所有平台上的线程问题,只需花费1个额外的函数,并在启动过程中为具有依赖项的单例程序实例化一些问题(当然,在断言的帮助下:明智地使用单例程序).

一种方法是确保在应用程序启动第二个线程之前,首先访问记录器。通过在您知道没有任何争用的时候访问singleton,您可以确保后续访问始终会找到预先存在的对象,并且您应该完全避免该问题。

您实际上不需要单独的Initialize()函数,因为这只会污染singleton接口。只需获取单例实例

VERIFY(NULL != Logger::Instance()); 

在任何其他线程有机会访问它之前。

您不希望instance()是静态的吗?它应该是
return&myinstance。不是返回
Singleton*
,而是返回
Singleton&
。它可以防止某人意外地执行以下操作:
Singleton*instance=Singleton::instance()。。。代码行。。。删除实例请不要返回指针。如果你这样做了,你就打开了一整罐关于谁拥有指针(以及谁应该释放它)的蠕虫。通过返回一个引用,您表明您的代码保留了所有权,因此将处理销毁。(在现代C++代码中,你几乎不应该返回原始指针)。@ PaulManta:因为他们可能认为他们可以删除它。如果您返回一个引用,他们现在无法删除。这是所有权的象征。这就是为什么你实际上从来没有传递好指针(没有任何所有权的指示),除非你仍然用C++编写C++(是的,那里有很多坏的C++)。在C++中,你可以传递引用或智能指针,因为这些都是所有权语义的指示。我倾向于喜欢这个答案,但是警告说,在预初始化代码中,你不能使用日志记录。这通常没什么大不了的,但我已经被它咬了一两次了。@Michael:当我们决定采用这种方法时,我实际上建议使用您的答案:在主线程中访问。但是这种方法对我们有效,它确保了单例总是在主线程中初始化。如果从主线程中删除访问权限,我们只会在第一次出现问题时(在现场?)才发现,我现有的代码非常接近这种方法。但是,我还想知道是否应该假设记录器的客户端代码始终正确地使用/初始化记录器,或者我应该在内部执行任何检查。@shiouming:use asserts:在调试模式下,除了first initialize(),您不能执行任何其他操作,尤其是因为您有一些用户设置。您是否存在先读取用户设置(不带记录器)然后才初始化记录器的依赖性问题?首先使用默认设置可以解决这个问题吗?是的,现有的实现在第一次调用getInstance()时使用默认设置,如果客户端没有初始化记录器的设置,或者它没有正确初始化。哇,我没想到响应会这么快。我才意识到我犯了一个愚蠢的错误。在我的例子中,基本上有两组需要保护的接口:getInstance(),其余的用于记录器的客户端初始化各种日志设置。我的错误是,我花了很多时间寻找一种方法来保护这两种类型的接口,希望能达到平衡的效率。为什么我必须使用一种方法,而且只能使用一种方法?对于getInstance(),我可以使用Arkaitz或stefaanv的建议;然后使用基本同步锁进行设置初始化。您不需要检查单个密码是否为空。它存在或不存在。返回对singelton gurantess的引用它存在。谢谢Mark。我同意单例getter必须返回引用,而不是指针。我的行指的是上面的关于Meyers singleton的片段,它通过指针返回。尽管看起来它不会失败,但您永远不知道谁会在将来修改您的代码。所以,请验证这只是未来程序员的时间胶囊。