ARC에서 싱글 톤의 공유 인스턴스 접근 자에 dispatch_once를 사용하는 정확한 이유는 무엇입니까?
+ (MyClass *)sharedInstance
{
// Static local predicate must be initialized to 0
static MyClass *sharedInstance = nil;
static dispatch_once_t onceToken = 0;
dispatch_once(&onceToken, ^{
sharedInstance = [[MyClass alloc] init];
// Do any other initialisation stuff here
});
return sharedInstance;
}
백그라운드에서 싱글 톤을 비동기 적으로 인스턴스화하는 것은 나쁜 생각이 아닙니까? 공유 인스턴스를 요청하고 즉시 의존하면 dispatch_once가 크리스마스까지 객체를 만들 때 어떻게됩니까? 바로 돌아 오지 않습니까? 적어도 그것은 그랜드 센트럴 파견의 요점 인 것 같습니다.
그들이 왜 이러는거야?
답변
dispatch_once()
절대적으로 동기입니다. 모든 GCD 메소드가 비동기식으로 작업을 수행하는 것은 아닙니다 (정확한 경우 dispatch_sync()
동기식 임). 를 사용 dispatch_once()
하면 다음 관용구 가 대체됩니다.
+ (MyClass *)sharedInstance {
static MyClass *sharedInstance;
@synchronized(self) {
if (sharedInstance == nil) {
sharedInstance = [[MyClass alloc] init];
}
}
return sharedInstance;
}
이것에 대한 장점은 dispatch_once()
더 빠르다는 것입니다. 또한 같은 시간에 모두 시도하면 sharedInstance의 할당을 수행하는 여러 스레드로부터 사용자를 보호하기 때문에 의미 론적으로 깨끗합니다. 두 개의 인스턴스를 만들 수 없습니다. 전체 아이디어 dispatch_once()
는 “한 번만 수행하고 한 번만 수행”하는 것입니다. 이것이 바로 우리가하는 일입니다.
답변
한 번만 실행되기 때문입니다. 따라서 다른 스레드에서 두 번 액세스하려고하면 문제가 발생하지 않습니다.
Mike Ash는 싱글 톤 관리 및 피드 블로그 게시물에 전체 설명이 있습니다.
모든 GCD 블록이 비동기 적으로 실행되는 것은 아닙니다.