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

[ios] GCD ( Grand Central Dispatch ) Tutorial

by 돼지왕 왕돼지 2017. 10. 24.
반응형

 [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 의 함수 포인터를 받는다.




반응형

댓글