In software engineering, the singleton pattern is a software design pattern that restricts the instantiation of a class to one single instance. This is useful when exactly one object is needed to coordinate actions across the system. The term comes from the mathematical concept of a singleton.
Singleton
Singleton ensures that only one object of a particular class is ever created.
Synchronized
When a thread calls the synchronized method ‘test’ of the object (here object is an instance of ‘TheDemo’ class) it acquires the lock of that object, any new thread cannot call ANY synchronized method of the same object as long as previous thread which had acquired the lock does not release the lock.
synchronized
blocks the next thread’s call to method test() as long as the previous thread’s execution is not finished. Threads can access this method one at a time. Without synchronized
all threads can access this method simultaneously.
1 | public class SOP { |
Volatile
volatile
has semantics for memory visibility. Basically, the value of a volatile
field becomes visible to all readers (other threads in particular) after a write operation completes on it. Without volatile
, readers could see some non-updated value.
1 | public class Foo extends Thread { |
volatile
is very useful to stop threads. One common example for using volatile
is to use a volatile boolean
variable as a flag to terminate a thread. In the above code segment, you need volatile because the thread reading close in the while loop is different from the one that calls close(). Without volatile, the thread running the loop may never see the change to close.
Double Checked Locking in Singleton
1 | public class DoubleCheckLocking { |
Since you are obtaining lock on the SearchBox.class
, only one thread will enter the synchronized block at a time. So the first thread enters then finds searchBox
is null and initilize the instance and then leaves the synchronized block, then the second thread enter the block then it finds that the searchBox
is not null because the first thread already created it so it will not create a new instance of searchBox
.
The double checked pattern is used to avoid obtaining the lock every time the code is executed. If the call are not happening together then the first condition will fail and the code execution will not execute the locking thus saving resources. Its purpose is to prevent unnecessary synchronization, thereby keeping your code fast in a multi-threaded environment.
Why volatile
The real problem is that Thread A may assign a memory space for instance before it is finished constructing instance. Thread B will see that assignment and try to use it. This results in Thread B failing because it is using a partially constructed version of instance.
If we do not make the searchBox variable volatile
then the Thread which is creating the instance of Singleton
is not able to communicate to the other thread. So if Thread A is creating Singleton instance and just after creation, the CPU corrupts etc, all other threads will not be able to see the value of searchBox as not null and they will believe it is still assigned null.
The value of this variable will never be cached thread-locally: all reads and writes will go straight to “main memory”; Access to the variable acts as though it is enclosed in a synchronized block, synchronized on itself.
Use cases
- The logging class
- Managing a connection to a database
- File manager
- Caching in Singleton