[iOS] - GCD 0. Info


Concurrency

Concurrency는 병행성이다.

그렇다면 무엇을 병행하는가? Concurrency는 여러 프로세스들을 병행적으로 처리하지만, 동시에 처리하지는 않는 것을 의미한다. 병행적으로 처리하는데 동시에 처리하지 않는다는 말이 모순적이라고 느낄 수 있지만, 병행적으로 처리하는 것과 동시에 처리하는 것은 엄연히 다른 개념이다.

Concurreny vs Parallelism

병행적으로 처리하는 것을 concurrent라 하고, 동시에 처리하는 것을 parallel이라고 한다.

  • 병행 : Concurrent
  • 동시 : Parallel

두 개념이 어떻게 다른 지 이해를 돕기 위해 Concurrency를 더 명확하게 설명하자면 concurrency는 두 개 이상의 프로세스가 하나의 공유 자원(CPU의 싱글 코어)을 갖고 context switching(문맥 교환)을 통해 번갈아 가며 실행되고 완료되는 것을 의미한다.

여기에서 중요한 점은 Context switching을 통해 번갈아 가며 실행된다는 점이다. 이는 같은 순간에 여러 프로세스들이 동시에 실행된다는 말이 아니다. 하나의 CPU만 갖고 있다면 한 순간에 두 개 이상의 프로세스를 처리할 수 없지만 같은 순간에는 앱 내에서 두 개 이상의 작업이 처리되고 있는 것이다.

예시

예를 들어 나한테 두 개의 작업이 할당되어 있는데, 하나는 노래 한 곡을 다 부르는 것이고, 다른 하나는 케이크 한 조각을 다 먹는 것이다. 이 두 작업을 병행적으로 처리하기 위해 노래를 한 구절 부르고, 케이크를 한 입 먹고, 또 노래를 한 구절 부르고, 또 케이크를 한 입 먹는 것을 반복하며 두 작업을 동시에 실행할 것이다. 노래를 부르면서 케이크를 먹을 수는 없다. 하지만 두 일을 동시에 하지 않아도 나는 이 두 작업을 병행적으로 처리하고 있는 것이다.

또는 형제자매가 있는 사람이라면 컴퓨터를 나눠 쓰는 경우를 빗대어서 생각하면 단번에 그 차이를 이해하기 쉬울 것이다.

  • Concurrent programming : 한 대의 컴퓨터를 여러 사람이 나눠 쓴다. 한 사람이 컴퓨터를 쓸 시간을 정해두고 돌아가면서 컴퓨터를 쓴다. 만약 한 사람이 컴퓨터를 쓰는 시간을 0.00000001초 정도로 할당한다면(실제로는 불가능하겠지만) 여러 사람이 한 대의 컴퓨터를 거의 동시에 쓰는 것처럼 보일 것이다.
  • Parallel programming : 여러 대의 컴퓨터를 여러 사람이 나눠 쓴다. 사람이 2명이고 컴퓨터도 2대 뿐이라면 한 명당 한 대씩 잡고 동시에 컴퓨터를 쓸 수 있다.

이제 ‘병행적’인 것을 의미하는 concurrency와 ‘동시적’인 것을 의미하는 parallelism의 가장 중요한 차이에 대해서는 어느 정도 이해가 됐을 것이다. 어떤 사람들은 parallelism과 concurrency를 비교했을 때 parallelism이 더 간단하다고 얘기한다.

Parallelism

Parallelism을 더 자세히 설명하면 같은 프로그램의 여러 복사본이 같은 시간에 실행되는데, 다른 기기에서 다른 데이터를 처리하는 것을 의미한다.

예를 들어 검색 엔진 회사는 웹 크롤링을 할 때 여러 대의 기기를 사용해서 크롤링을 할 수도 있다. 각 머신은 웹 사이트에 요청을 보내는 하나의 프로그램을 실행하는데, 기기마다 다른 URL들을 처리할 수도 있기 때문에 웹 크롤링의 결과로 다양한 종류의 컨텐츠를 다운로드 할 수 있을 것이다. 이때 여러 기기들에서 프로그램들이 “parallel 하게” 실행된다고 한다.

이렇게 parallel하게 실행하면 전체 URL 목록을 한 대의 기기에서 처리하는 것보다 크롤링하는 작업을 더 빠르게 끝낼 수 있다. 이런 상황에서 프로그램의 각 copy들을 하나의 “instance”로 볼 수 있다.

Concurrency

Concurrency는 같은 프로그램의 여러 복사본이 같은 시간에 실행되는데, 실행될 때 각 복사본들이 서로 소통할 수 있을 때 일어난다. 한 대의 기기만 사용할 때 일반적으로 많은 간단한 concurrent 애플리케이션에서는 프로그램의 instruction 코드가 메모리에 한 번만 load된다. 즉, 하나의 프로세스가 생성되었지만 프로세스는 여러 개의 thread를 생성해서 실행 중인 것이다. 각 쓰레드는 각각 어느 명령어를 실행중인지를 기억한다. 그래서 쓰레드는 저마다의 control flow가 있는데, 다른 쓰레드에서의 정보를 바탕으로 결정을 내릴 수도 있다.

다른 쓰레드의 정보들을 받으려면 다른 쓰레드와 소통할 수 있어야 한다. 두 쓰레드는 shared memory를 통해 소통할 수 있는데, 한 쓰레드가 쓰면 다른 쓰레드가 읽는 방식이다. 하지만 공유 메모리에 데이터를 쓰는 시점에 따라 읽는 값들이 달라질 수 있다. 심지어 읽기와 쓰기가 같은 순간에 발생한다면, 읽는 입장에서는 일부분만 업데이트된 값을 읽게 도리 수도 있다. 이런 상황을 피하기 위해서 synchronization 명령어를 실행하는데, 한 쓰레드가 다른 쓰레드가 특정 연산을 다 수행하기 전까지 기다리게 하는 것이다.


Section 1에서는 Concurrency의 기본에 대해 배울 것이다. Concurrency가 무엇인지, concurrency를 통해 어떤 문제를 해결할 수 있는지, 왜 사용하는지 등을 알 수 있다.

추가로 iOS 개발에서의 concurrency의 기본이 되는 두 가지 요소를 공부할 것이다.

  1. Grand Central Dispatch
  2. Operations

이 섹션에서는 Concurrency의 가장 기본적인 개념을 볼 것이다. 다음 챕터들에서는 각 개념을 더 자세히 살펴볼 것이다.

  1. Chapter 1: Introduction : Concurrency가 무엇인지와 왜 사용해야 하는지를 볼 것이다.
  2. Chapter 2: GCD vs. Operations: Concurrency는 Grand Central Dispatch(GCD) 나 Operations를 통해 다룰 수 있다. 이 둘의 차이를 보고 어떤 것을 선택해야 하는지를 볼 것이다.
  • 참고
  • https://medium.com/@itIsMadhavan/concurrency-vs-parallelism-a-brief-review-b337c8dac350
  • https://www.quora.com/What-is-concurrency-in-programming
  • https://www.geeksforgeeks.org/concurrency-in-operating-system/
  • https://www.educative.io/answers/what-is-concurrent-programming