'Thread'에 해당하는 글 1건

원본 : http://www.raywenderlich.com/60749/grand-central-dispatch-in-depth-part-1

위 링크의 강좌를 2포스트에 걸쳐서 번역을 진행할 것이다. 본 포스트는 위 원문 포스팅의 절반을 번역한 것이다.


Update note : Swift를 사용한 iOS8 기반의 Grand Central Dispatch tutorial 최신 튜토리얼이 있다!

비록 Grand Central Dispatch(혹은 줄여서 GCD)가 얼마동안 주변에 있어 왔다고 해서, 모두가 그것을 잘 아는건 아니다. 이것은 이렇게 이해될 수 있다; 동시에 하는것은 편법이고, C기반 API의 GCD는 Objective-C의 세계로 자연스럽게 뽀죡한 끝으로 푹 찌르는 것처럼 보인다. 깊이있게 두 파트의 시리즈를 가진 Grand Central Dispatch 강좌를 배워보자.

이 두 파트에서, 첫번째 강좌에서는 GCD가 뭘하는지와 GCD 기능 기반의 몇몇 예시를 보여줄것이다. 두번째 파트는 GCD가 가진 더 많은 기능적인 이점을 배울 것이다. 



GCD란?
GCD는 libdispatch를 위한 마케팅적인 이름이다, 애플 라이브러리는 iOS와 OSX의 멀티코어 하드웨어에서 코드 동시 실행을 위한 기능을 제공한다. 이것은 아래 이점들을 따른다:
  • GCD는 무거운 처리를 살짝 뒤로 미루고 백그라운드에서 처리할 수 있게 도와주므로써  당신 앱의 대응력을 높혀준다.
  • GCD는 쓰레드를 락 거는것 보다 더 쉬운 동시 실행 모델을 제공하고 동시 실행시 생기는 버그들을 피할 수 있게 도와준다.
  • GCD는 싱글톤으로써 일반적인 패턴의 높은 퍼포먼스와 함께 당신의 코드를 아름답게 만들어 줄 것이다.
이 강좌는 블록코딩과 GCD가 어떻게 동작하는지 잘 알고있다는 가정하에 진행한다. 만약 GCD를 처음 접한다면 Multithreading and Grand Central Dispatch on iOS for Beginners를 먼저 필수로 보고 오면 좋겠다.


GCD 용어
GCD를 이해하기위해, 여러분은 쓰레딩과 동시실행어대한 몇몇 개념을 명확하게 할 필요가 있다. 이것들은 둘다 모호하고 헷갈리는 것이지만 잠시 다시 GCD의 관점에서 그것들을 가볍게 생기시켜 봐야한다.
(역자 주 : 원문에서는 GCD 용어라고 해놓았지만, 구글에 "쓰레드 용어"로 검색하면 더 많은 정보를 얻을 수 있다)

Serial vs. Concurrent
이 용어는 작업들이 서로관에 연관이되어 실행되는 경우를 설명하는 용어이다. 연속적으로 실행되는 작업들은 항상 한번에 실행된다. 작업들은 한번에 동시에 실행되어야한다.

비록 이 용어가 넓은 응용프로그램이지만, 이 강의의 목적상 당신은 Objective-C block 작업 수행에만 초점을 맞출 수 있다. block이 뭔지 모른다고? 여기 이 강좌(How to Use Blocks in iOS 5 Tutorial)를 참고해라. 사실 당신은 또한 함수포인터와 함께 GCD를 사용할 수 있지만, 대부분의 케이스에서는 이것이 사용에 실질적이고 편법적이다. Block은 매우 편하다!



Synchronous vs. Asynchronous
GCD에서, 이 용어는 함수가 연관된 다른 작업을 끝났을때 함수는 실행하기위해 GCD에게 물어보는 것을 뜻한다. 동기화(synchronous) 함수는 명령된 일이 모두 끝난 후에 리턴한다.

반면 비동기화(asynchronous) 함수는 즉시 리턴하고, 일이 다 끝났다고 알려주지만 실제 일이 끝날때까지 기다리지는 않는다. 그러므로 비동기화 함수는 다음 함수에서 처리되는 실행의 현재 쓰레드 block이 아니다.

조심하자 - 현재 쓰레드의 동기화 함수 “blocks”을 읽을때나 함수가 “blocking”함수 이거나 blocking operation인경우 혼동하지 말자! blocks라는 동사는 어떻게 한 함수가 현재 쓰레드에 영향을 미치는지이고 명사 block과는 아무 연관이 없다. 명사 block는 Objective-C에서 이름없는 함수의 용어이고 GCD에 보내는 일들을 정의한다.

Critical Section
이것은 한번에 두 쓰레드가 도는 상황에서 반드시 동시에 실행되지 않는 코드 조각이다. 동시 프로세스에 의해 접근된다면, 이것은 코드가 (변수와 같은) 공유된 자원을 동시에 건드릴 수 있기 때문에 잘못된 값이 들어가거나 할 수 있다.

Race Condition
---

Deadlock
만약 그 두가지(혹은 그 이상)의 일이 서로의 처리가 끝나기를 기다리고 있을때 이것을 deadlock 되었다고 부른다(대부분의 쓰레드에서 나타날 수 있다). 첫번째 처리는 두번째 처리가 끝나기를 기다리기 때문에 끝날 수 없다. 그러나 두번째 처리 또한 첫번째 처리가 끝나기를 기다리기 때문에 두번째 처리도 끝날 수가 없을 것이다.

Thread Safe
쓰레드 세이프 코드는 여러 문제(데이터 오염, 크래쉬 등등)를 피하면서 멀티쓰레딩이나 동시처리로부터 안전하게 콜이 가능하다. 쓰레드 세이프가 되지 못한 코드는 한번에 한 콘텍스 안에서 동작한다. 쓰레드 세이프 코드 중 하나는 NSDictionary이다. 당신은 멀티 쓰레드 이슈 없이 저것을 이용할 수 있다. 반면 NSMutableDictionary는 쓰레드 세이프가 아니다. 이것은 오직 한번에 한 쓰레드안에서 접근할 수 있다.

Context Switch
context switch는 당신이 한 싱글 프로세스에서 다른 쓰레드를 실행하여 전환할 때의 저장 및 복구 실행 상태의 프로세스이다. 이 프로세스는 멀티쓰레딩하는 앱을 만들때 아주 일반적인 방법이지만, 이것은 추가적인 비용이 따른다.

Concurrency vs Parallelism

참고 한글 자료 : http://skyul.tistory.com/263
Concurrency와 parallelism은 종종 함께 거론된다. 그래서 짧게 그 두개를 비교하여 설명할 것이다.

concurrent 코드의 나눠진 부분은 “동시에” 실행될 수 있다. 그러나 그것이 어떻게 처리되는지는 시스템이 정하기 나름이다.

멀티코어 디바이스는 병렬적으로 같은 시간에 멀티 쓰레딩을 실행시키지만, 싱글코어 디바이스는 이것을 수행하기 위해 쓰레드를 실행시키고, 컨텍스 스위칭을 동작하며, 다른 쓰레드나 프로세스를 작동시킨다. 이것은 아래 그림처럼 마치 병렬적으로 수행되게 보이는데 충분히 빨리 수행된다.

비록 당신이 GCD에서 동시수행을 코드에 사용했었어도, 얼마나 병렬수행이 필요한지 GCD가 정하기 나름이다. 병력수행은 동시에 일어나는 것을 요구한다. 그러나 ‘동시’는 보장된 병렬을 제공하지 않는다.

중요한 포인트는 ‘동시’는 사실 구조에 관한 것이다. 당신이 GCD를 코드에 사용할 생각이 있을 때, 당신은 동시에 일어날 수 있는 일의 부분을 당신 코드 구조체에 노출한다. 게다가 한개는 반드시 동시에 일어나지 않는다. 만약 당신이 이 주제에대해 더 깊게 알고싶으면 this excellent talk by Rob Pike를 확인해보아라.

Queues

GCD는 코드의 블럭들을 다룰 수 있게
dispatch queues를 제공한다; 큐(queue)들은 당신이 GCD에 제공한 테스크를 관리하거나 FIFO 명령에 의한 테스크를 실행시킨다. 첫 테스크를 큐에 추가하는데 이점은 첫번째 테스크가 큐에서 시작되고 두번째로 추가된 테스크가 두번째에서 시작할것이며, 차례로 될 것이다. 

모든 dispatch queues는 당신이 멀티쓰레드에서 동시에 접근하려해도 스스로 쓰레드 세이프하다. 이러한 GCD의 이점은 어떻게해서 dispatch queues가 당신의 코드의 부분에서 쓰레드-세이프한 것을 제공하는지 이해할때 나타날 것이다. 이것의 핵심은 옳은 dispatch queue 종류와 옳은 dispatching function을 골라서 당신의 일의 queue에 보내기 위함이다.

이 섹션에서 특별한 GCD queue가 제공하는 두가지 종류의 dispatch queue를 보게 될 것이다, 그리고 GCD dispatching function과 함께
큐에 어떻게 추가하는지 알려주는 형상화한 예제를 돌려볼 것이다.

Serial Queues

serial queues에서 데스크는 한번에 한회만 실행된다, 각 테스크는 이전 실행되는 테스크가 끝나고나야지만이 시작된다. 뿐만아니라, 아래 그림과같이 우리는 한 블럭의 끝나는 점과 다음 블럭의 시작하는 점의 시간차이를 알지도 못한다.

이 테스크의 동작 타이밍은 GCD의 컨트롤 아래에 이루어진다; 당신이 알고 있는 GCD의 이점은 한번에 한번만 수행한다는것과 queue에 추가되어서 명령을 받으면 테스크를 실행한다는 것이다.

Seiral queue에서는 절때 동시에 두 테스크가 실행될 수 없으나, 동시실행에서 같은 섹션을 접근할 위험은 없다; 이 테스크를 오직 수행한다는 점에서 race condition으로부터 섹션이 위험해지는것을 막는다. 그러므로 위험한 섹션에 접근 할 수 있는 유일한 방법은 dispatch queue에 테스크를 담아서 보내는 방법이다, 그리고 위험한 섹션이 안전하다는 것을 검증받을 수 있다.



Concurrent Queues

concurrent queues에 테스크들은 추가하라는 명령에서 시작하는 보장을 가지고... 그것은 당신이 완전히 보장됬다는 것을 의미한다! 요소들은 어떤 명령들도 끝낼 수 있고 당신이 다음 블럭이 언제 시작될건지 모르거나 많은 블럭이 얼마동안 시간을 잡아먹으면서 동작하는지 몰라도된다. 이것이 GCD의 모든것이다.

아래 그래프는 GCD에서 4개의 동시수행을 동작하는 테스트 샘플이다.


Block 1, 2, 3 모두가 어떻게하면 빨리 연이어서 실행될지 주목하라, Block0이 시작된 후 블럭1이 시작되는 동안 일어날 것이다. 또한 Block3은 Block2 다음에 시작되지만 Block2보다 빨리 끝난다.

block이 언제 시작되는지의 결정은 완전히 GCD에서 한다. 만약 block의 실행 시간이 다른것과 겹칠때, 다른 코어에서 실행시킬지, 한개만 사용할것인지 혹은 코드를 다른 block에 콘텍스 스위칭을 할지 정하는건 GCD가 하기 나름이다.

단지 흥미로운 점은 GCD가 각자 다른 queue 타입으로부터 정해서 적어도 5가지의 각 queue들을 제공한다는 점이다.


Queue Types

처음으로, 이 시스템은 당신이 main queue라고 알고있는 특별한 종류의 큐를 제공한다. 다른 queue들과 같이, 이 큐에서도 한번에 테스크를 수행한다. 그러나 이것은 모든 테스크를 메인 스레드에서 수행할 것이라는 뜻이며, 당신의 UI를 유일하게 업데이트 할 수 있는 스레드이기도하다. 이 queue는 UIView에 메세지를 보내거나 노티피케이션을 보내는 것에 사용되어야하는 유일한 queue이다.

시스템은 또한 여러 동시 queues를 제공한다. 이것은 우리가 알고있는 Global Dispatch Queues라고 불리는 놈이다. 이것은 다른 우선순위를 가진 4개의 global queue가 있다: backgroundlowdefault, and high

마지막으로, 당신은 커스텀화된 종류나 동시 queues 또한 생성할 수 있다. 이 말은 당신이 적어도 5개의 queue들을 마음대로 생성 소멸시킬 수 있다는 뜻이다: main queue, 4개의 global dispatch queues, 추가로 당신이 커스텀화시켜 만든 queues 까지!

그리고 dispatch queue들의 큰 그림이 있다!

GCD의 예술적인 면은 queue에 당신의 일을 적당한 queue dispatching function을 골라 보내는 역할을 한다는 것이다. 이것을 경험하기 가장 좋은 방법은 권장해놓은 길을 따라서 예제를 실행해보는 것이다.



WRITTEN BY
tucan.dev
개인 iOS 개발, tucan9389

,