Perfect solution to the lazy thread safety problem in the singleton design pattern
- 2020-05-26 08:30:42
- OfStack
First, write a singleton:
public class SingleDemo {
private static SingleDemo s = null;
private SingleDemo(){}
public static SingleDemo getInstance(){
if(s == null){
s = new SingleDemo();
}
return s;
}
}
Write a test class:
public class ThreadDemo3 {
public static void main(String[] args) {
SingleDemo s1 = SingleDemo.getInstance();
SingleDemo s2 = SingleDemo.getInstance();
System.out.println(s2 == s2);
}
}
Run result 1 is true, it is no problem under single thread, let's write a multi-thread to access the singleton
public class ThreadTest implements Runnable {
// Store singleton object, use Set This is to avoid storing duplicate elements
public Set<SingleDemo> singles = new HashSet<SingleDemo>();
@Override
public void run() {
// Access to the singleton
SingleDemo s = SingleDemo.getInstance();
// Add a singleton
singles.add(s);
}
}
Using multithreaded concurrent access singletons:
public class ThreadDemo3 {
public static void main(String[] args) {
// SingleDemo s1 = SingleDemo.getInstance();
// SingleDemo s2 = SingleDemo.getInstance();
// System.out.println(s2 == s2);
ThreadTest t = new ThreadTest();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
System.out.println(t.singles);
}
}
The results are as follows:
[com.persagy.thread.SingleDemo@1bc4459, com.persagy.thread.SingleDemo@150bd4d]
or
[com.persagy.thread.SingleDemo@12b6651]
It shows that there is a thread access security problem, not 1 must be the same one instance
How do you solve the thread safety problem?
Of course we use the synchronous lock mechanism
The following improved singleton:
public class SingleDemo {
private static SingleDemo s = null;
private SingleDemo(){}
public static synchronized SingleDemo getInstance(){
if(s == null){
s = new SingleDemo();
}
return s;
}
}
The thread safety problem was resolved when the synchronization function was added
Run multiple times to get the same instance, there will not be two instances
[com.persagy.thread.SingleDemo@12b6651]
However, in the case of concurrent access by multiple threads, each thread needs to judge the lock every time it gets an instance, which is inefficient. In order to improve the efficiency, I added the method of dual judgment to solve the problem of efficiency
The code is as follows:
public class SingleDemo {
private static SingleDemo s = null;
private SingleDemo(){}
public static SingleDemo getInstance(){
/* If the first 1 Four threads get the instance object of the singleton,
* The later thread does not need to go into the synchronized block to retrieve the instance */
if(s == null){
// The lock used for synchronizing code blocks is the singleton's bytecode file object, and only this lock can be used
synchronized(SingleDemo.class){
if(s == null){
s = new SingleDemo();
}
}
}
return s;
}
}
In this way to solve the lazy thread safety problem, also improve the efficiency, but in the actual development or to use the hungry han more, after all, this code is more, more tedious.