[Effective Objective-C] #45 스레드 안전한 단일 시간 코드 실행은 dispatch_once 를 이용하라
출처 : Effective Objective-C
-
싱글턴 디자인 패턴은 보통 shared instance 라는 클래스 메서드를 통해 구현된다.
이는 매번 새로운 인스턴스를 할당하는 대신 클래스의 싱글턴 인스턴스를 반환한다.
@implementation EOCClass
+ (id)sharedInstance{
static EOCClass *sharedInstance = nil;
@synchronized(self){
if ( !sharedInstance){
sharedInstance = [[self alloc] init];
}
}
}
@end
-
싱글턴의 화재는 스레드 안전에 대한 것이다.
싱글턴 인스턴스를 생성하는 부분을 스레드 안전하게 만들기 위해 동기화 블록으로 둘러쌓았다.
좋든 싫든 이 패턴은 흔히 사용되고 있고 이런 코드는 아주 흔한 코드다.
-
그러나 GCD 에는 싱글턴 인스턴스를 훨씬 쉽게 구현하도록 도와주는 기능이 있다.
그 함수는 다음과 같다.
vodi dispatch_once(dispatch_once_t *token, dispatch_block_t block);
이 함수는 dispatch_once_t 라는 특수 타입을 파라미터로 받는다.
나는 이 파라미터들을 '토큰(token)' 과 블록으로 부를 것이다.
이 함수는 주어진 토큰을 이용해 블록이 한 번에 한 개씩 실행되는 것을 보장한다.
블록은 항상 처음 한 번만 실행된다.
그리고 가장 중요한 것은 스레드 안전하게 실행된다는 점이다.
각 블록이 정확히 한 번만 실행되도록 하기 위해 전달하는 토큰은 항상 같은 것이어야 한다.
이는 보통 토큰 변수를 static 이나 global 로 선언하는 것을 의미한다.
-
+(id)sharedInstance{
static EOCClass *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
dispatch_once 를 사용하면 코드가 간단해지고 완전한 스레드 안전이 보장된다.
그렇기 때문에 락킹이나 동기화를 고려하지 않아도 된다.
GCD 의 깊숙한 곳에서 다 처리된다.
토큰은 static 으로 선언된다.
매번 완전히 동일한 토큰이어야 하기 때문이다.
-
dispatch_once 는 훨씬 효율적이다.
코드가 실행될 때마다 락을 획득하는 무거운 동기화 기술을 사용하는 대신 디스패치 토큰에 코드가 실행되었는지 여부를 알려주는 원자적 접근(atomic access)을 사용한다.
기억할 점
-
스레드 안전 단일 코드(single-code) 실행은 흔히 하는 작업이다.
GCD 는 이를 위한 사용하기 쉬운 dispatch_once 함수라는 도구를 제공한다.
-
토큰은 static 이나 global 로 선언해야 한다.
반드시 한 번만 실행되어야 하는 각 블록을 위해 전달되는 토큰이 같은 것이어야 하기 때문이다.
'프로그래밍 놀이터 > iOS' 카테고리의 다른 글
[ios] permission category (0) | 2017.10.12 |
---|---|
[ios] 권장되는 permission guide (0) | 2017.10.11 |
[Effective Objective-C] #44 플랫폼 확장의 이점을 얻으려면 디스패치 그룹을 사용하라 (0) | 2017.10.09 |
[Effective Objective-C] #43 GCD 가 필요한 때와 작업 큐가 필요한 때를 구분해서 알아두라 (0) | 2017.10.08 |
[Effective Objective-C] #42 performSelector 메서드군보다는 GCD 를 사용하라 (0) | 2017.10.07 |
댓글