[ios] GCD( Grand Central Dispatch) Tutorial
참조 : http://www.letmecompile.com/gcd-%ED%8A%9C%ED%86%A0%EB%A6%AC%EC%96%BC/
디스패치 큐의 종류
-
Custom Serial & Concurrent Dispatch Queue
dispatch_queue_t serialQueue = dispatch_queue_create(“queueSerial”, DISPATCH_QUEUE_SERIAL);
dispatch_queue_t concurrentQueue = dispatch_queue_create(“queueConcurrent”, DISPATCH_QUEUE_CONCURRENT);
-
System Dispatch Queue
dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_queue_t globalConcurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
// 중요도에 따라 HIGH, DEFAULT, LOW, BACKGROUND 로 나뉜다.
디스패치 큐의 릴리즈 시점
-
Custom Dispatch Queue 를 만들어 사용한 경우에는 해당 큐를 release 해주어야 한다.
dispatch_release(myQueue);
dispatch_async 를 사용해 queue 를 전달한 경우에, 해당 queue 에 내용물이 남아있어도 정상적으로 끝까지 실행이 된다.
-
ARC 를 사용하는 경우에는 dispatch_release 를 통해 release 해줄 필요가 없다.
디스패치 시간 조절
-
// 3초 후에 queue 에 Task(block)을 넣고 싶다면..
dispatch_time_t dispatchTime = dispatch_time(DISPATCH_TIME_NOW, 3*NSEC_PER_SEC);
dispatch_after(tm, queue, ^{ } );
디스패치 그룹
-
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, anyQueue, ^{ NSLog{@“block 1”);});
dispatch_group_async(group, anyQueue, ^{ NSLog{@“block 2”);});
dispatch_group_async(group, anyQueue, ^{ NSLog{@“block 3”);});
dispatch_group_notify(group, dispatch_get_main_queue(). ^{ NSLog(@“Called after group jobs are done”) }; // no-blocking
// dispatch_group_wait(group, time); // blocking
dispatch_release(group); // ARC 에서는 필요 없음
Concurrent Queue 에서 async 작업간의 순서 정하기
-
dispatch_asnyc(concurrent_queue, ^{ NSLog(@“block 1”); });
dispatch_asnyc(concurrent_queue, ^{ NSLog(@“block 2”); });
dispatch_asnyc(concurrent_queue, ^{ NSLog(@“block 3”); });
dispatch_barrier_async(concurrent_queue, ^{NSLog(@“this block is called after block 1, 2, 3”;});
dispatch_asnyc(concurrent_queue, ^{ NSLog(@“block 4”); });
block1, block2, block3 이 호출된 후 "this block is called after block 1, 2, 3" 이 찍히고, 이후에 block 4 가 호출되는 것이 보장된다.
그러나 이 때 block1, block2, block3 의 호출 순서는 보장되지 않는다.
데드락을 일으키는 코드
-
dispatch_sync(dispatch_get_main_queue(), ^{NSLog(@“This log will not be shown?”);});
// 메인 스레드에서 이 코드를 실행 시 문제가 된다.
-
dispatch_async(serialQueue, ^{
dispatch_sync(serialQueue, ^{NSLog(@“This log will not be shown”);});
});
// SerialQueue 에서 sync 가 불리며 lock 이 잡혀 데드락이 된다.
디스패치 이터레이션
-
배열에 대해 dispatch를 이용해 작업을 적용하고 싶을 때 dispatch_apply 를 활용할 수 있다.
dispatch_async(queue, ^{
dispatch_apply( [myArray count], queue, ^(size_t index){
NSLog(@“Object at %ld is %@“, index, [myArray objectAtIndex:index];
});
dispatch_async(dispatch_get_main_queue(), ^{
// update UI
});
});
디스패치 실행 멈춤/재개
-
아래 코드를 이용하여 큐에 쌓여있는 블록의 실행을 멈추거나 재개할 수 있다. ( 취소는 안된다. )
큐에 남아있는 녀석들에 대한 control 만 가능하다.
dispatch_suspend(queue)
dispatch_resume(queue)
디스패치 세마포어 ( semaphore )
-
디스패치 세마포어를 이용하면 디스패치간에 공유되는 변수에 여러 스레드가 동시에 접근하는 것을 막을 수 있다.
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
for( int i=0; i < 100; i++ ){
dispatch_async(queue, ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); // wait 가 풀리면 0
[mutableArray addObject:@“object”];
dispatch_semaphore_signal(semaphore); // +1 하며 resource 다 썼다고 표기
});
}
앱 실행 후 딱 한번만 디스패치하기
-
+(instancetype)sharedInstance{
static dispatch_once_t once;
static id sharedInstance;
dispatch_once(&once, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
위 코드와 같이 singleton 을 구현할 때 주로 쓰인다.
GCD 에서 블록대신 함수 사용하기
-
지금까지 설명된 dispatch 함수들에 _f 가 접미어로 붙는 녀석들은 블락 대신 C 의 함수 포인터를 받는다.
'프로그래밍 놀이터 > iOS' 카테고리의 다른 글
[ios] Solution for "The resource could not be loaded because the App Transport Security policy requires the use of a secure connection" (0) | 2017.10.26 |
---|---|
[ios] String Concat ( String 연결하기 ) (0) | 2017.10.25 |
[ios/design pattern] private 메서드 정의하기 (0) | 2017.10.23 |
[Effective Objective-C] 총 정리 (0) | 2017.10.22 |
[Effective Objective-C] 목차와 요약을 통해 한 눈에 알아보는 Effective Objective-C #49~#52 (0) | 2017.10.21 |
댓글