본문 바로가기
프로그래밍 놀이터/iOS

[Effective Objective-C] #45 스레드 안전한 단일 시간 코드 실행은 dispatch_once 를 이용하라

by 돼지왕왕돼지 2017. 10. 10.

 [Effective Objective-C] #45 스레드 안전한 단일 시간 코드 실행은 dispatch_once 를 이용하라


출처 : Effective Objective-C

@ synchronized, dispatch_block_t, dispatch_once, dispatch_once_t, dispatch_once, GCD, Global, shared instance, single-code, Singleton, static, thread safe, token, [Effective Objective-C] #45 스레드 안전한 단일 시간 코드 실행은 dispatch_once 를 이용하라, 단일 시간 코드 실행, 동기화 블록, 락 획득, 락킹, 무거운 동기화 기술, 스레드 안전, 스레드 안전 단일 코드, 싱글턴, 싱글턴 디자인 패턴, 원자적 접근, 토큰, 효율적


-

싱글턴 디자인 패턴은 보통 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 로 선언해야 한다.

반드시 한 번만 실행되어야 하는 각 블록을 위해 전달되는 토큰이 같은 것이어야 하기 때문이다.




댓글1