먼저 스레드로부터 안전하지 않은 초기화 싱글턴 모드를 살펴보겠습니다
public class UnsafeLazyInitialization { private static UnsafeLazyInitialization instance; public static UnsafeLazyInitialization getInstance(){ if(instance == null){ //1: 线程A执行 instance = new UnsafeLazyInitialization(); //2: 线程B执行 } return instance; } }
UnsafeLazyInitialization 클래스에서 스레드 A가 코드 1을 실행하면 스레드 B가 코드 2를 실행한다고 가정합니다. 시간 스레드 A는 인스턴스 참조 개체가 아직 초기화되지 않았음을 확인할 수 있습니다.
UnsafeLazyInitialization 클래스의 경우 getInstance() 메서드를 동기화하여 스레드로부터 안전한 지연 초기화를 달성할 수 있습니다. 샘플 코드는 다음과 같습니다.
public static synchronized UnsafeLazyInitialization getInstance(){ if(instance == null){ //1: 线程A执行 instance = new UnsafeLazyInitialization(); //2: 线程B执行 } return instance; } }
위 코드는 getInstance() 메서드를 동기화하므로 이로 인해 동기화 프로그램이 발생할 수 있습니다. 오버헤드가 증가합니다. getInstance()를 여러 스레드에서 자주 호출하면 프로그램 실행 성능이 저하되고, 반대로 여러 스레드에서 호출되지 않으면 getInstance() 메서드의 초기화 방식이 지연되어 성능에 영향을 미치게 됩니다.
JVM 1.6 이전에는 동기화가 무거운 잠금이므로 성능을 많이 소모하므로 사람들은 성능 향상을 위해 이중 확인 잠금(Dobule-check Locking) 솔루션을 생각했습니다. 샘플 코드는 다음과 같습니다.
public class DoubleCheckedLocking { //1、 private static Instance instance; //2、 public static Instance getInstance(){ //3、 if(instance == null){ //4、第一次检查 synchronized (DoubleCheckedLocking.class){ //5、枷锁 if(instance == null){ //6、第二次检查 instance = new Instance(); //7、问题的根源在这里 } //8、 } } return instance; } }
위 코드에 표시된 것처럼 4단계의 첫 번째 검사가 null이 아닌 경우 다음 잠금 작업을 수행할 필요가 없으므로 동기화된 잠금으로 인해 발생하는 성능 문제가 크게 줄어듭니다. 위의 코드에는 문제가 없는 것 같습니다. 1. 여러 스레드 보기가 새 개체를 생성할 때 동기화 키워드를 사용하면 단 하나의 스레드만 개체를 성공적으로 생성하도록 할 수 있습니다.
2. 인스턴스 객체가 생성되었다면 getInstatnce() 메소드를 통해 직접 객체 인스턴스를 얻어옵니다.
위 코드는 완벽해 보이지만 4단계가 실행되면 즉시 실행됩니다! =null, 인스턴스의 참조 개체가 아직 초기화되지 않았을 수 있습니다.
위의 7단계 코드를 실행하면, object = new Instance();가 생성되는데, 이 객체 생성 단계는 다음과 같이 세 단계로 나눌 수 있습니다.
위의 코드 2와 3의 세 줄은 순서가 바뀔 수 있습니다. (JTI 컴파일러에서는 실제로 순서가 바뀌는 일이 발생합니다.) 2단계와 3단계를 순서대로 바꾼 후의 실행 순서memory = allocate() //1.分配内存空间memory ctorInstance(memory) //2, 初始化对象在内存 分配内存空间memory上初始化 Singleton 对象 instance = memory //3、设置 instance 指向刚分配的内存地址memory
memory = allocate() //1.分配内存空间memory instance = memory //3、设置 instance 指向刚分配的内存地址memory // 注意此时instance对象还没有被初始化,但是instance的引用已经不是null了。 ctorInstance(memory) //2, 初始化对象在内存 分配内存空间memory上初始化 Singleton 对象
위 내용은 Java에서 이중 확인 잠금 문제를 해결하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!