0

I'm learning about the Singleton Pattern. You can find something about it here https://en.wikipedia.org/wiki/Singleton_pattern.

I'm learning it from from the "Head First Design Patterns" book and they specifically say that synchronization is one of the bigger problems with this patterns.

They have 2 ways to handle it in Java.

  1. They Synchronize the GetInstance() method:

    • in Java they simply do this using the synchronized keyword public static synchronized Singleton GetInstance(){...
    • I think this is the best way to do it in C++ but I could not find a good way to do it, almost all of the ways I found is using global variables, and well... This pattern should in stop the use of the global variables and makes it kind of ironic.
  2. Use eager Instantiation:

    • the other way they do it using eager Instantiation, meaning they instantiate create the object and just return the creation with the GetInstance() method.

    This in C++ can be done like this: Singleton *Singleton::UniqueInstance = new Singleton(); (You would still have to do it outside the class because of "Incomplete type is not allowed error")

    • The reason why I do not like this is because it wastes memory. Meaning if I do not use the class it will just use the memory without actually needing to. The other reason is if you would like to pass an argument to the constructor, this seems impossible using this way.
    • I don't think this is a good long term fix. Please do correct me if I am wrong.

So my question is how to fix this in C++? How can I Synchronize the methods? I understand that in Java Synchronizing these methods lowers the speed of the program by a factor of 100. They use a simple optimizing method but I don't know if it is the same in C++.

I also saw something about the Synchronize attribute but I'm not sure if I understand that correctly.

François Andrieux
  • 28,148
  • 6
  • 56
  • 87
Oogway101
  • 83
  • 1
  • 5
  • 2
    *"This pattern should stop the use of the global variables and makes it kind of ironic."* No, the Singleton design pattern is basically "global variable, the pattern". It is the pattern of using a global variable. It is normal to have to use a global `mutex` to synchronize a singleton (a global object). – François Andrieux Aug 12 '21 at 18:37
  • 6
    The Meyers' Singleton implementation of the Singleton design pattern is thread safe as far as initialization goes since C++11. It seems to me like this is a better alternative to both proposed solutions. But if multiple threads are concurrently accessing the singleton object in a way that causes a race condition, the singleton itself needs to be synchronized and none of these solutions will help you. – François Andrieux Aug 12 '21 at 18:39
  • 1
    I'm with @FrançoisAndrieux If you must have a singleton, make it a Meyers', not what you found in the wikipage - and then sync in the methods. – Ted Lyngmo Aug 12 '21 at 18:42
  • 4
    [Link to great answer on the Meyers Singleton](https://stackoverflow.com/a/1008289/4581301). – user4581301 Aug 12 '21 at 18:49
  • Inexpensive synchronization is possible, in C++ as well as Java, but only in certain cases. You have to know going in that your case qualifies for the approach you intend to use--which means you've picked the approach based on what you know about your case--otherwise you'll get fast-but-not-correct behaviour. Expensive synchronization is easy, but worthless. Finding balance typically means you protect as little as possible--what you need to protect and nothing more--and only when you need to. – user4581301 Aug 12 '21 at 18:55
  • Thank you for the information I checked out how the Mayors' Singleton works but I'm a little confused how this fixes the issue? How does this assure that it's thread safe? – Oogway101 Aug 12 '21 at 18:59
  • Meyer's singleton protects access to the singleton itself. For example, Meyers singleton handles the case of "What if two threads try to simultaneously create the singleton?" You'll also need to protect the data contained by the singleton, and we can't offer good advice on that without knowing what the data is and the access pattern. One general recommendation: Don't merely protect access to the data, protect the transaction. – user4581301 Aug 12 '21 at 18:59
  • @user4581301 thank you for your link suggestion. If I were to check if the Instance is null and then use synchronize wouldn't that make it more efficient? Then it would synchronize the method only at the first time and the other times it won't need to. – Oogway101 Aug 12 '21 at 19:01
  • Again use transaction-based thinking. What if the instant between thread A checking for NULL and locking the mutex to create the singleton thread B checks for NULL and creates the singleton? You need to protect the whole transaction: both the check AND the creation. – user4581301 Aug 12 '21 at 19:03
  • @user4581301 I've been examining this method for a while now. I'm still confused how this creates it thread-safe, What is the difference between this and creating the variable as private in the class itself? Mayer creates the instance of type singleton in a static variable and then returns that variable. He creates it at the time when the create method is called, I understand how that saves it from wasting memory. I understand how he removes the creation and cloning possibility and how he makes sure it is going to delete the variable. But I do not understand how he makes it thread-safe. – Oogway101 Aug 12 '21 at 19:48
  • This is a hard-to-find bit of information if you don't know where to look for it. As of C++11, C++ guarantees that the initialization of `static` variables is thread safe. [See cppreference's notes on static local variables](https://en.cppreference.com/w/cpp/language/storage_duration#Static_local_variables) for a good, human-language description. – user4581301 Aug 12 '21 at 20:17
  • 1
    Ha! I did know where to look for it and it STILL took too long to find it and be able to edit it in. http://eel.is/c++draft/stmt.dcl#4 – user4581301 Aug 12 '21 at 20:24
  • Ohhh! I understand now! The reason because Mayer's code is thread safe is because of the usage of static variables! That is very interesting to know. thank you all for helping me out and thank you @user4581301 for putting the effort here! – Oogway101 Aug 12 '21 at 22:32

0 Answers0