지금은 위의 말이 무슨 말인지 와닿지 않을 수 있다. 앞으로 글을 읽다보면 이해가 될 것이다.
설명하기전 우리가 앱을 만드는 방식을 살펴보면 아래의 사진처럼 UI를 제작하고 Logic을 구성하고 UI 또는 Data를 업데이트할 것이다. 이 때 Logic 구성과 UI/Data 업데이트를 우리는 앞으로 Task(작업단위)로 칭할 것이다.
수업을 한 예시로 Thread를 표현하면 아래의 사진처럼 표현할 수 있다.
아래의 사진을 보면 어색한 부분이 있는데 그 부분은 수업과 필기가 따로 행해지고 있다는 것이다. 위의 표현처럼 수업이 진행된다고 하면 선생님이 수업를 시작하고 수업을 멈추고 학생이 필기를 시작하고 필기를 멈추면 선생님이 다시 수업을 시작하는 형식으로 진행될 것이다.
하지만 실제 수업은 선생님은 계속 필기하고 학생은 가끔 필기를 하는 형태로 진행된다. 이 수업을 다시 그림을 그려보면 아래와 같다.
이 상황이 바로 Multi - Thread이고 이전에 수업 필기가 한 Thread에서 반복되었던 것이 Single - Thread이다.
이제 이 상황을 iOS로 바꾸어보면 아래와 같이 바뀔 것이다.
TableView로 비유하자면 데이터를 추가하면 그 데이터를 Main Thread에서 추가하고 그리고 데이터를 삭제(수정)하면 Main Thread에서 삭제해준다.
통장에 200만원이 있을 때 맥북을 구매하고 월세를 내야한다고 가정해보자. 맥북을 구매하고 월세를 낸다고 쳤을 때 맥북을 구매하면 10초뒤 통장에서 돈이 나가고 월세는 바로 빠져나간다고 생각해보자. 그렇다면 잔고는 1300000원이 남을 것이다.
코드로 작성한다면
전역 var money = 2000000
func apple() {
var myMoney = money
usleep(10000000)//10초
myMoney -= 1500000
money = myMoney
}
func houseMoney() {
var myMoney = money
myMoney -= 700000
money = myMoney
}
//최종적으로 우리는 멕북도 사고 월세도 냈지만 1300000원이 잔고로 남게된다.
이 문제를 바로 공유자원의 문제라고 한다.
Multi - Threading을 계속하다보면 발생할 수 있는 문제이다.
이 문제를 해결하는 방법으로 크리티컬섹션, 뮤텍스, 세마포어로 해결할 수 있다.
위의 개념은 읽기만 해도 무슨 말인지 모르겠다. 따라서 개념보다는 그냥 작동 원리에 대해서 설명하겠다.
하나의 공유자원이 있고 2개의 Thread(?)가 있다고 생각해보자.
하나의 공유자원에 A라는 Thread가 작업을 하고 있던 도중에 B라는 Thread가 작업을 하러 들어오는게 가능할까?
불가능하다. 이렇게 하나의 Thread가 작업을 하러 들어간 상태에서 아직 작업이 끝나지 않았다면 다른 Thread가 들어갈 수 없는 것을 말한다.
자, 이제 여기서 질문을 다시 해보겠다.
Multi - Thread만 좋은 것인가??
정답은 아니다.
Single - Thread의 단점이 있듯 Multi - Thread도 단점이 있기 때문이다.
팀플을 예로 들어서 Single - Thread를 능력있는 팀원 혼자 업무를 수행한다고 생각하고 Multi - Thread를 능력있는 팀원 1명 버스 타는 팀원 3명이 있다고 생각하면 당연히 팀의 효율은 Single - Thread가 더 좋을 것이다.
또한 팀원 혼자 수행하던 업무를 4명이 있는 팀원에게 주면 수행이 가능할까? 사람으로 따지면 가능하지만 OS로 따지면 각 팀원마다 수행가능한 업무가 있으므로 수행이 불가능하다. 또한 Single - Thread에서도 Multi - Thread에서 수행가능한 작업을 수행할 수 있다. 이러한 이유로 Multi - Thread만 좋다는 생각은 옳지 않다.
자원 접근데 대한 동기화를 신경쓰지 않아도 된다.
여러개의 스레드가 공유된 자원을 사용할 경우, 각 스레드가 원하는 결과를 얻게 하려면 공용 자원에 대한 접근이 통제되어야 하며, 이 작업은 프로그래머에게 많은 노력을 요구하고 많은 비용을 발생시킨다. 단일 스레드 모델에서는 이러한 작업이 필요하지 않다.
작업전환 작업을 요구하지 않는다.
작업전환은 여러 개의 프로세스가 하나의 프로세서를 공유할 때 발생하는 작업으로 많은 비용을 필요로 한다.
여러 개의 CPU를 활용하지 못한다.
프로세서를 최대한 활용하게 하려면 cluster 모듈을 사용하거나, 외부에서 여러 개의 프로그램 인스턴스를 실행시키는 방법을 사용해야 한다.
두 개의 작업을 하나의 스레드로 처리하는 경우와, 두 개의 스레드로 처리하는 경우를 가정했을 때, 후자의 경우는 짧은 시간 동안 2개의 스레드가 번갈아가면서 작업을 수행한다. 그래서 동시에 두 작업이 처리되는 것과 같이 느끼게 된다.
하지만 오히여 두 개의 스레드로 작업한 시간이 싱글스레드로 작업한 시간보다 더 걸릴 수도 있는데, 그 이유는 스레드 간의 작업전환(context switching)에 시간이 걸리기 때문이다.
따라서 단순히 CPU만을 사용하는 계산작업이라면, 오히려 멀티스레드보다 싱글스레드로 프로그래밍하는 것이 더 효율적이다.