참고 : www.mikeash.com
향후 아이패드2나 아이폰5 등 멀티코어 환경에서 개발을 하려는 사람들에게는
꼭 알아두어야 할 기술이 바로 이 GCD 가 아닐까 한다.
* 2011-10-20에 추가됨
이번에 IOS5 가 나오면서 GCD 에 변경된 부분이 있다.
간추려보면
1. 새로운 global queue 추가(DISPATCH_QUEUE_PRIORITY_BACKGROUND)
2. custom concurrent queue
3. Dispatch IO
자세한 사항은 여기를 참조
1. GCD (Grand Central Dispatch)
concurrent programming을 위한 저수준 C API.
작업을 분리하고 work queues에 저장후, 동시에 혹은 하나씩 작업을 처리.
(NSOperationQueue와 비슷하나 좀더 저수준이고 높은 성능을 보인다고 한다).
dispatch object = GCD 는 객체지향 개념으로 만들어졌다. GCD 객체를 일컬음.
메모리 관리 필요 : dispatch_retain, dispatch_release
Dispatch Queues: 처리할 작업을 받아들이기 위한 객체. concurrent / serial 이 존재.
동시에 작업을 처리(시스템 부하를 고려하여)하거나 하나씩 작업을 처리한다.
3가지 큐 존재
Main queue: serial queue.
메인 쓰레드가 처리하게 된다.
dispatch_get_main_queue() 호출로 얻을수있다.
Global queues: concurrent queues
전체 프로세스가 공유하며, 3종류 존재
(high,default,low priority queue).
동시에 작업을 수행한다.
dispatch_get_global_queue() 호출로 접근가능 (priority 지정필요).
Custom queues: serial queue.
한번에 하나씩 작업을 처리한다.
dispatch_queue_create()로 생성된다.
2. 사용법
1) 큐를 생성 (위의 함수 호출 이용)
custom queue 경우 다음처럼 호출.
1 | dispatch_queue_create("com.yourcompany.subsystem.task", NULL); |
Pastie #2500485 linked directly from Pastie.
2) 처리할 작업을 전달한다.
1 2 3 4 5 6 | dispatch_async(dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ ; NSLog(@"Done doing something long and involved"); }); |
Pastie #2500430 linked directly from Pastie.
dispatch_async 함수는 즉시 리턴되며, 작업은 비동기적으로
백그라운드에서 수행된다.
* 중첩된 dispatche.
시간이 걸리는 작업 종료후 UI변경등이 필요한 경우
UI처리는 main thread 에서 수행되어야 하므로 중첩된 호출을 통해 가능함.
1 2 3 4 5 6 7 8 9 | dispatch_async(dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ ; dispatch_async(dispatch_get_main_queue(), ^{ ; }); }); |
Pastie #2500436 linked directly from Pastie.
처리할 작업(block)이 종료될때까지 기다리는 경우 dispatch_sync 사용.
__block 변수 : 살행중인 block으로부터 결과를 받을수 있음. 만약 백그라운드
작업중인 쓰레드에서 GUI 컴트롤 값을 필요로 하는 경우 다음처럼 사용가능.
1 2 3 4 5 6 7 8 9 10 11 12 13 | //백그라운드 쓰레드내에서의 소스. //현재 이쓰레드가 백그라운드로 작업중이라고 가정. __block NSString *stringValue; dispatch_sync(dispatch_get_main_queue(), ^{ // __block 변수는 자동으로 retain 되지 않음. // reference 를 확실하게 만들어서 관리한다. stringValue = ; }); ; // 그리고 stringValue를 백그라운드 쓰레드에서 사용한다. |
Pastie #2500450 linked directly from Pastie.
쓰레드등을 이용한 백그라운드 프로세싱을 중첩된 block을 이용하여 아래처럼
교체가능하다.
1 2 3 4 5 6 7 8 9 | dispatch_queue_t bgQueue = myQueue; //global 혹은 custom 큐. dispatch_async(dispatch_get_main_queue(), ^{ NSString *stringValue = ; dispatch_async(bgQueue, ^{ // 이부분에 들어가는 소스는 백그라운드로 수행되며 // stringValue 를 사용할수 있다. }); }); |
Pastie #2500459 linked directly from Pastie.
3) Lock을 대체하기 위해서 이렇게도 사용 가능하다.
일반적인 경우가 다음과 같다면,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | NSLock *lock; //getter - (id)something { id localSomething; [lock lock]; localSomething = [[something retain] autorelease]; [lock unlock]; return localSomething; } //setter - (void)setSomething:(id)newSomething { [lock lock]; if(newSomething != something) { [something release]; something = [newSomething retain]; [self updateSomethingCaches]; } [lock unlock]; } |
Pastie #2500472 linked directly from Pastie.
다음처럼 바꿀수 있다.
이때 큐는 custom (즉 serial)큐만 가능하다. 동기 /비동기 처리를
활용하는것임. 즉 , 비동기(dispatch_async)로 동기화가 필요한 함수를
호출하면 백그라운드에서는 dispatch_sync로 처리되어 serial하게
작업을 처리한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | - (id)something { __block id localSomething; dispatch_sync(queue, ^{ localSomething = [something retain]; }); return [localSomething autorelease]; } - (void)setSomething:(id)newSomething { dispatch_async(queue, ^{ if(newSomething != something) { [something release]; something = [newSomething retain]; [self updateSomethingCaches]; } }); } |
Pastie #2500480 linked directly from Pastie.
dispatch queue 사용이 매우 가벼워서 lock을 거는 빈도가 많아도 무방함.
더욱 온전한 내용을 원하신다면 원문을 참조하기 바랍니다...
댓글 없음:
댓글 쓰기