자바 싱글 톤 및 동기화
싱글 톤 및 멀티 스레딩에 대한 내 질문을 명확히하십시오.
- 다중 스레드 환경에서 Java로 Singleton을 구현하는 가장 좋은 방법은 무엇입니까?
- 여러 스레드
getInstance()
가 동시에 메서드에 액세스하려고하면 어떻게됩니까 ? - 싱글 톤을 만들 수 있습니까
getInstance()
synchronized
? - Singleton 클래스를 사용할 때 동기화가 정말로 필요합니까?
네, 필요합니다. 지연 초기화로 스레드 안전성을 달성하는 데 사용할 수있는 몇 가지 방법이 있습니다.
드라코 니안 동기화 :
private static YourObject instance;
public static synchronized YourObject getInstance() {
if (instance == null) {
instance = new YourObject();
}
return instance;
}
이 솔루션을 사용하려면 실제로 처음 몇 개만 동기화 해야 할 때 모든 스레드를 동기화해야합니다.
동기화 재확인 :
private static final Object lock = new Object();
private static volatile YourObject instance;
public static YourObject getInstance() {
YourObject r = instance;
if (r == null) {
synchronized (lock) { // While we were waiting for the lock, another
r = instance; // thread may have instantiated the object.
if (r == null) {
r = new YourObject();
instance = r;
}
}
}
return r;
}
이 솔루션은 싱글 톤 획득을 시도하는 처음 몇 개의 스레드 만 잠금 획득 프로세스를 거치도록합니다.
요청시 초기화 :
private static class InstanceHolder {
private static final YourObject instance = new YourObject();
}
public static YourObject getInstance() {
return InstanceHolder.instance;
}
이 솔루션은 스레드 안전성을 보장하기 위해 클래스 초기화에 대한 Java 메모리 모델의 보장을 활용합니다. 각 클래스는 한 번만로드 할 수 있으며 필요할 때만로드됩니다. 즉, 처음 getInstance
호출되고 InstanceHolder
로드되고 instance
생성되며 ClassLoader
s에 의해 제어 되므로 추가 동기화가 필요하지 않습니다.
이 패턴은 명시 적 동기화 없이 인스턴스의 스레드로부터 안전한 지연 초기화를 수행합니다 !
public class MySingleton {
private static class Loader {
static final MySingleton INSTANCE = new MySingleton();
}
private MySingleton () {}
public static MySingleton getInstance() {
return Loader.INSTANCE;
}
}
It works because it uses the class loader to do all the synchronization for you for free: The class MySingleton.Loader
is first accessed inside the getInstance()
method, so the Loader
class loads when getInstance()
is called for the first time. Further, the class loader guarantees that all static initialization is complete before you get access to the class - that's what gives you thread-safety.
It's like magic.
It's actually very similar to the enum pattern of Jhurtado, but I find the enum pattern an abuse of the enum concept (although it does work)
If you are working on a multithreaded environment in Java and need to gurantee all those threads are accessing a single instance of a class you can use an Enum. This will have the added advantage of helping you handle serialization.
public enum Singleton {
SINGLE;
public void myMethod(){
}
}
and then just have your threads use your instance like:
Singleton.SINGLE.myMethod();
Yes, you need to make getInstance()
synchronized. If it's not there might arise a situation where multiple instances of the class can be made.
Consider the case where you have two threads that call getInstance()
at the same time. Now imagine T1 executes just past the instance == null
check, and then T2 runs. At this point in time the instance is not created or set, so T2 will pass the check and create the instance. Now imagine that execution switches back to T1. Now the singleton is created, but T1 has already done the check! It will proceed to make the object again! Making getInstance()
synchronized prevents this problem.
There a few ways to make singletons thread-safe, but making getInstance()
synchronized is probably the simplest.
Enum singleton
The simplest way to implement a Singleton that is thread-safe is using an Enum
public enum SingletonEnum {
INSTANCE;
public void doSomething(){
System.out.println("This is a singleton");
}
}
This code works since the introduction of Enum in Java 1.5
Double checked locking
If you want to code a “classic” singleton that works in a multithreaded environment (starting from Java 1.5) you should use this one.
public class Singleton {
private static volatile Singleton instance = null;
private Singleton() {
}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class){
if (instance == null) {
instance = new Singleton();
}
}
}
return instance ;
}
}
This is not thread-safe before 1.5 because the implementation of the volatile keyword was different.
Early loading Singleton (works even before Java 1.5)
This implementation instantiates the singleton when the class is loaded and provides thread safety.
public class Singleton {
private static final Singleton instance = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return instance;
}
public void doSomething(){
System.out.println("This is a singleton");
}
}
You can also use static code block to instantiate the instance at class load and prevent the thread synchronization issues.
public class MySingleton {
private static final MySingleton instance;
static {
instance = new MySingleton();
}
private MySingleton() {
}
public static MySingleton getInstance() {
return instance;
}
}
What is the best way to implement Singleton in Java, in a multithreaded environment?
Refer to this post for best way to implement Singleton.
What is an efficient way to implement a singleton pattern in Java?
What happens when multiple threads try to access getInstance() method at the same time?
It depends on the way you have implemented the method.If you use double locking without volatile variable, you may get partially constructed Singleton object.
Refer to this question for more details:
Why is volatile used in this example of double checked locking
Can we make singleton's getInstance() synchronized?
Is synchronization really needed, when using Singleton classes?
Not required if you implement the Singleton in below ways
- static intitalization
- enum
- LazyInitalaization with Initialization-on-demand_holder_idiom
Refer to this question fore more details
Java Singleton Design Pattern : Questions
public class Elvis {
public static final Elvis INSTANCE = new Elvis();
private Elvis () {...}
}
Source : Effective Java -> Item 2
It suggests to use it, if you are sure that class will always remain singleton.
참고URL : https://stackoverflow.com/questions/11165852/java-singleton-and-synchronization
'Programming' 카테고리의 다른 글
새 툴바의 제목 색상은 어떻게 설정합니까? (0) | 2020.08.08 |
---|---|
구에 n 개의 점을 균등하게 분배 (0) | 2020.08.08 |
Java에서 뮤텍스와 세마포어는 무엇입니까? (0) | 2020.08.08 |
Ruby : 문자열의 첫 번째 문자를 얻는 방법 (0) | 2020.08.08 |
중첩 된 사전의 값을 가져 오는 Python 안전한 방법 (0) | 2020.08.08 |