By now, you know what the problem is, but I'll list the possible causes I know about here (assuming a GOF compliant Singleton pattern:
1. Race condition in first call to instance()
This is a constant worry in multithreaded applications. The situation is that two threads call instance() at the same time, in both cases the static/class variable show the instance to be null, so both threads create the instance and assign it, the first of which is a leaked object in a non-GC language.
Solutions:
a. Create your instance in your main thread, before other threads are created. In some cases, this is not possible.
b. Synchronize within the instance() method. Many a developer has turned their nose at this one, because instance() should be as fast as possible. If so, use Double-Checked Locking, which avoids the synchronization as much as possible. A word of caution to Java programmers, there is considerable debate as to whether DCL is reliable in Java.
2
This is probably the trickiest problems to understand at first. If your singleton is linked into multiple executable modules (shared libraries/dlls and main executable) the static instance reference will be defined multiple times. Shared libraries share code, not data.
This really applies beyond singletons - it effects all static members and global data you use. These global members are "global" to the module.
3.C++ Global memory initialization.
As we all become painfully aware, in C++ there are no guarantees of the initialization order of globals defined in separate units. In other words, global initialization had better be as trivial as possible.
If a global object has a non-trivial constructor which invokes instance() on a singleton, or if a global pointer is initialized with an instance() call to a singleton, it opens the program up to the Multiton problem.
The way it could happen is like this:
Global variables being initialized...
Global variable constructor calls instance()
Singleton instance created
Singleton's _instance is initialized (back to NULL)
main() executes
Code calls instance()
New Singleton instance is created
(Big thanks to On Freund for suggesting #3)
Solution:
Take control of your initialization order by changing, where necessary global objects to global pointers, initialized to NULL, and initialize them in main()
No comments:
Post a Comment