싱글 톤의 이중 체크 잠금
여기 싱글 톤 패턴에 대한 커스텀 클래스가 있습니다. 이 코드에서는 아래와 같이 이중 확인 잠금을 사용합니다. 일부 소스에서 많은 게시물을 읽었을 때 두 개의 동시 스레드가 동시에 실행되는 것을 방지하여 두 개의 다른 개체를 만드는 것을 방지하기 때문에 이중 검사가 유용하다고 말합니다.
public class DoubleCheckLocking {
public static class SearchBox {
private static volatile SearchBox searchBox;
// private constructor
private SearchBox() {}
// static method to get instance
public static SearchBox getInstance() {
if (searchBox == null) { // first time lock
synchronized (SearchBox.class) {
if (searchBox == null) { // second time lock
searchBox = new SearchBox();
}
}
}
return searchBox;
}
}
나는 여전히 위의 코드를 너무 많이 이해하지 못합니다. 인스턴스가 null 일 때 두 스레드가 함께 동일한 코드 줄을 실행하면 문제는 무엇입니까?
if (searchBox == null) {
synchronized (SearchBox.class) {
if (searchBox == null) {
searchBox = new SearchBox();
}
}
}
그것이 나타날 때. 두 스레드 모두 object is null을 보게됩니다. 그런 다음 둘 다 동기화합니다. 그런 다음 다시 확인하고 여전히 null을 봅니다. 두 개의 다른 개체를 만듭니다. OOOPS.
설명해주세요. 내가 무엇을 잘못 이해 했습니까?
감사 :)
아니요,에서 잠금을 얻고 있으므로 SearchBox.class
한 번에 하나의 스레드 만 동기화 된 블록에 들어갑니다. 따라서 첫 번째 스레드가 입력하면 searchBox
null이 발견 되고 생성 된 다음 동기화 된 블록을 떠난 다음 두 번째 스레드가 블록에 들어간 다음 searchBox
첫 번째 스레드가 이미 생성했기 때문에이 (가) null이 아님을 발견 하므로 새 인스턴스를 생성하지 않습니다. searchBox
.
이중 체크 패턴은 코드가 실행될 때마다 잠금을 얻지 않도록하기 위해 사용됩니다. 호출이 함께 발생하지 않으면 첫 번째 조건이 실패하고 코드 실행이 잠금을 실행하지 않으므로 리소스가 절약됩니다.
이 코드를 살펴 보겠습니다.
1 if (searchBox == null) {
2 synchronized (SearchBox.class) {
3 if (searchBox == null) {
4 searchBox = new SearchBox();
5 }
6 }
이것에 대해 추론 해 봅시다. 두 개의 스레드가 A
있고 B
그 중 적어도 하나가 라인 3에 도달하고 관찰되는 스레드 searchBox == null
가 true
. 블록 으로 인해 두 개의 스레드 가 동시에 라인 3에있을 수 없습니다synchronized
. 이것이 이중 확인 잠금이 작동하는 이유를 이해 하는 열쇠 입니다. 따라서 먼저 A
또는 먼저 B
통과 한 경우 여야합니다 synchronized
. 일반성을 잃지 않고 해당 스레드가 A
. 그런 다음 searchBox == null
true를 확인하면 문의 본문에 입력하고 searchBox
의 새 인스턴스로 설정 합니다 SearchBox
. 그런 다음 결국 synchronized
블록을 종료합니다 . 이제 B
들어갈 차례입니다. 기억하세요.B
A
종료를 기다리는 동안 차단되었습니다 . 이제 블록에 들어가면 searchBox
. 그러나 값 이 아닌 값으로 A
설정 searchBox
하면 남을 것 null
입니다. 끝난.
그런데 Java에서 싱글 톤을 구현하는 가장 좋은 방법은 단일 요소 enum
유형 을 사용하는 것 입니다. 에서 효과적인 자바 :
이 접근 방식은 아직 널리 채택되지 않았지만 단일 요소 열거 형은 단일 항목을 구현하는 가장 좋은 방법입니다.
이 이중 검사 잠금은 싱글 톤을 동시에 호출하는 스레드가 많거나 일반적으로 잠금을 얻는 비용이 걱정되는 경우에만 필요합니다.
그 목적은 불필요한 동기화를 방지하여 다중 스레드 환경에서 코드를 빠르게 유지하는 것입니다.
If you are running in Java 1.5 or greater, and you use the volatile
keyword in your double-check locked mechanism, it will work fine. As you are using the volatile
keyword, your example is not broken according to the same link above.
if (searchBox == null) { //1
synchronized (SearchBox.class) {
if (searchBox == null) { //2
searchBox = new SearchBox();
}
}
}
}
- If an instance was already created, don't do anything - avoid locking threads
- The first thread that has acquired the lock checks and sees that there is no such object and creates it. It releases the lock and the second one can do the same - it has to check if the object exists because the first one may have created it.
So basically the outer if
is used to prevent redundant locks - it lets all thread know that there is already an object and they don't need to lock/do anything. And the inner if
is used to let a concurrent thread know whether another has already created the object or not.
참고URL : https://stackoverflow.com/questions/18093735/double-checked-locking-in-singleton
'code' 카테고리의 다른 글
Javascript에서 삭제 연산자의 목적은 무엇입니까? (0) | 2020.12.01 |
---|---|
쿼리가 조인 가져 오기를 지정했지만 가져온 연결의 소유자가 선택 목록에 없습니다. (0) | 2020.12.01 |
Android Studio에서 프로젝트를 bitbucket 저장소로 가져 오는 방법은 무엇입니까? (0) | 2020.12.01 |
BroadcastReceiver 대 WakefulBroadcastReceiver (0) | 2020.12.01 |
Ansible : sudo 권한이있는 사용자 생성 (0) | 2020.12.01 |