![]() |
1
11
如果使用Visual C++ 2005/2008,则可以使用双重检查锁定模式,因为“ volatile variables behave as fences “。这是实现惰性初始化单例的最有效方法。
每当需要访问singleton时,只需调用getsingleton()。第一次调用时,静态指针将被初始化。初始化后,空检查将阻止仅读取指针的锁定。 不 在任何编译器上使用这个,因为它不可移植。该标准没有保证这将如何工作。VisualC++ 2005明确地增加了易失性的语义,使之成为可能。 你得申报 initialize the CRITICAL SECTION 代码中的其他地方。但这种初始化很便宜,所以延迟初始化通常并不重要。 |
![]() |
2
13
一种简单的保证方法 单实例的跨平台线程安全初始化 在应用程序的主线程中显式地执行(通过调用singleton上的静态成员函数) 之前 您的应用程序启动任何其他线程(或至少任何其他将访问该单例的线程)。 然后,使用互斥锁/关键部分,以通常的方式确保线程安全地访问singleton。 延迟初始化 也可以使用类似的机制来实现。遇到的常见问题是,提供线程安全性所需的互斥体通常是在单实例本身中初始化的,这只会将线程安全问题推到互斥体/关键部分的初始化。解决这个问题的一种方法是在应用程序的主线程中创建和初始化互斥/关键部分,然后通过调用静态成员函数将其传递给singleton。然后,可以使用这个预初始化的互斥/关键部分,以线程安全的方式对单例进行重量级初始化。例如:
然而,有充分的理由避免使用单件(以及为什么有时它们被称为 反模式 ):
另一种方法是使用“逻辑单例”,在主线程中创建并初始化类的单个实例,并将其传递给需要它的对象。如果有许多对象要作为单例创建,这种方法可能会变得笨拙。在这种情况下,可以将不同的对象捆绑到单个“context”对象中,然后在必要时传递该对象。 |
![]() |
3
4
虽然我喜欢接受的解决方案,但我发现了另一个有前途的线索,并认为我应该在此分享: One-Time Initialization (Windows) |
![]() |
4
1
您可以使用操作系统原语(如mutex或critical部分)来确保线程安全初始化,但是每次访问singleton指针时(由于获取锁),这都会导致开销。它也是不便携的。 |
![]() |
5
1
对于这个问题,你需要考虑一个澄清点。你需要…
在Web上有很多示例在C++中实现这些模式。这里有一个 Code Project Sample |
![]() |
6
0
下面解释了如何在C中完成这项工作,但完全相同的概念适用于任何支持单例模式的编程语言。 http://www.yoda.arachsys.com/csharp/singleton.html 您需要决定的是您是否需要延迟初始化。惰性初始化意味着在第一次调用singleton时就创建了它内部包含的对象。 前任:
如果直到稍后才进行该调用,则线程之间存在争用条件的危险,如本文所述。但是,如果你
在代码的开头,假设它是线程安全的,然后您就不再懒惰地初始化了,当应用程序启动时,您将需要“一些”更多的处理能力。但是,如果你这样做的话,它会解决很多关于比赛条件的难题。 |
![]() |
7
0
|
![]() |
8
0
这个问题不需要单例是懒惰构造还是不需要。 由于许多答案都是假设的,所以我假设第一个短语讨论: 鉴于语言本身不是线程意识,加上优化技术,编写一个可移植的可靠C++单元格是非常困难的(如果不是不可能的话),请参见 C++ and the Perils of Double-Checked Locking 作者:斯科特·迈尔斯和安德烈·亚历山大·斯库。 我已经看到许多答案都是通过使用criticalsection在Windows平台上同步对象,但是criticalsection只有在所有线程都在一个处理器上运行时才是线程安全的,今天可能不是这样。 msdn-cite:“单个进程的线程可以使用关键节对象进行互斥同步。”. 和 http://msdn.microsoft.com/en-us/library/windows/desktop/ms682530(v=vs.85).aspx 进一步澄清: 关键部分对象提供的同步与互斥对象提供的同步类似,只是关键部分只能由单个进程的线程使用。 现在,如果不需要“惰性构造”,那么下面的解决方案是跨模块安全和线程安全,甚至是可移植的:
它是跨模块安全的,因为我们使用本地范围的静态对象而不是文件/命名空间范围的全局对象。 它是线程安全的,因为:在输入main或dllmain之前,必须将x-singleton-helper赋给正确的值。它不是懒惰的构造,也因为这个事实),在这个表达式中,逗号是一个运算符,而不是标点符号。 在这里显式地使用“extern”来防止编译器优化它(关注Scott Meyers的文章,最大的敌人是优化器),并使静态分析工具如pc lint保持沉默。在main /dLmain中,Scott meyer被称为“单线程启动部分”,在“有效C++第三”项4中。 但是,我不太确定是否允许编译器根据语言标准优化get_x_instance()的调用,请评论。 |
![]() |
9
-1
有很多方法可以在Windows上执行线程安全的singleton*初始化。事实上,其中一些甚至是跨平台的。在你链接到的so线程中,他们正在寻找一个用c懒散地构造的单例,这有点具体,而且考虑到你正在使用的内存模型的复杂性,做正确的工作可能会更复杂一些。
|
![]() |
S qasem · Android内存性能 7 年前 |
![]() |
R83nLK82 · 在单例设计模式上引发IOException 7 年前 |
![]() |
hal · 两个课程有什么区别?他们的工作方式不同吗? 7 年前 |
![]() |
Jaquarh · 如何在不使用DI的情况下实例化父类 7 年前 |
|
Deepanshu · 基于PHP的Web应用程序中的单例对象状态 7 年前 |
![]() |
dicle · 视图控制器中的依赖项注入 7 年前 |
![]() |
Kozuki · 如何在生产代码中考虑单例? 7 年前 |