본문 바로가기

잡다한 개발잡담

프로세스와 스레드의 차이를 알아보자

프로세스와 스레드
프로세스는 실행중인 프로그램을
의미하고, 스레드는 프로세스의 실행단위이다. 그러므로 스레드는 프로세스 내에서 동작되는 여러 실행흐름이라고 말할 수 있다. 또 신기한 것은 프로세스 간의 통신보다 스레드 간의 통신의 속도가 빠르다고 한다.
아래의 사진이 프로세스와 스레드의 차이를 정말 적절하게 보여주는 것 같다.

스레드간의 통신 속도가 더 빠른거야?
위의 사진을 보니까 왜 스레드간의 통신 속도가 더 빠른지 알것만 같다..사진상으로 가까이 있으니까..? 비슷한것 같다. 정확히 설명하자면 위의 사진에서 스레드들은 한 프로세스 안에서 존재한다. 그렇다면 이렇게 생각해 볼 수 있다. 저 프로세스 내에서 어떤 데이터 영역을 프로세스끼리 공유하고 있다면 컨텍스트 스위칭의 비용이 줄어들지 않을까?

그렇다. 한 프로세스 내에서 스레드들은 코드/데이터/힙 영역을 공유하여 사용하며 각자의 스레드는 별도의 스택 영역을 할당받는다. 즉 스레드내에서의 변수생성은 스레드의 스택 영역에 저장되어 스레드 간에 공유할 수 없지만 코드/데이터/힙 영역은 공유되므로 이 공유 영역에 접근하여 통신할 수 있어, 컨텍스트 스위칭의 비용이 줄어든다.

또한, 컨텍스트 스위칭이 일어날 때, 캐시 메모리를 비우는 과정을 거치지 않아도 되는 것도 이유 중 하나이다.

컨텍스트 스위칭이 뭔데..? 캐시 메모리를 왜 비우지? .. 
컨텍스트 스위칭은 한 Task가 끝날 때 까지 기다리지 않고, 여러 작업을 번갈아가면서 실행해야 할 때, 동시에 처리될 수 있도록 하는 방법이다.  이전의 TASK의 상태(문맥)를 보관하고 새로운 프로세스의 상태를 적재하는 작업을 말한다. 

컨텍스트 스위칭 과정이 일어나는 동안에 CPU는 아무런 일을 할 수 없는 상태가 된다. 그러므로 컨텍스트 스위칭이 자주 일어날 경우 오버헤드가 발생해 성능이 저하된다.

또한, 캐시는 CPU와 메인 메모리 사이에 위치하면서 CPU에서 한번 이상 읽어들인 메모리의 데이터를 보관하다가, 다시 그 메모리를 요청하게 되면 메인 메모리에 요청하는 것이 아니라 캐시에서 바로 데이터를 전달해주는 역할을 하게 된다. 이 캐시때문에 멀티스레드 프로그래밍 시에 동기화를 해주어 데이터가 불일치하지 않도록 해줘야 한다.

만약 프로세스에서 컨텍스트 스위칭이 일어난다면 공유하는 데이터가 없으므로 캐시의 데이터를 모두 지우고 새로 캐시 정보를 쌓아야 한다. 그렇지만 스레드라면?? 저장된 캐시 데이터는 이미 공유하는 데이터가 있으므로 의미 없는 데이터가 아니다. 그래서 프로세스는 캐시 데이터를 지우는 비용이 추가적으로 소모되지만 스레드는 소모되지 않는다.

이런 좋은 멀티 쓰레딩의 단점은 무엇이 있을까?

멀티 프로세스 기반으로 프로그래밍 시에 프로세스 간 공유하는 자원이 없다. 그러므로 동일한 자원에 동시에 접근하는 일이 없을텐데, 멀티 스레딩을 기반으로 한다면 공유 영역에대한 동시 접근이 발생하면서 데이터의 정합성에 대한 문제가 발생할 수 있다. 그러므로 데이터 동기화를 반드시 신경써줘야한다.

또한, 멀티 스레드 환경에서 하나의 스레드에서 치명적인 에러가 발생한다면? 전체 스레드가 종료될 수 있다는 문제점도 가지고 있다. 멀티 프로세스 환경에서는 하나의 프로세스가 죽이되든 밥이되든 다른 프로세스에는 영향을 끼치지 않지만 말이다.

동기화?? 어떻게 해야할까

공유 영역 데이터에 동시에 접근해서 발생하는 문제니까 동시에 접근하는 것을 막으면 되지 않을까? Critical Section(임계영역)이란 동일한 자원을 동시에 접근하는 작업을 실행하는 코드 영역을 Critical Section이라고 말하는데 이러한 임계 영역을 제어하기 위해 아래와 같은 조건을 충족시켜야 한다.

  • Mutual Exclusion(상호 배제)
    프로세스 P1 이 Critical Section 에서 실행중이라면, 다른 프로세스들은 그들이 가진 Critical Section 에서 실행될 수 없다.
  • Progress(진행)
    Critical Section 에실행중인 프로세스가 없고, 별도의 동작이 없는 프로세스들만 Critical Section 진입 후보로서 참여될 수 있다.
  • Bounded Waiting(한정된 대기)
    P1 가 Critical Section 에 진입 신청 후 부터 받아들여질 때가지, 다른 프로세스들이 Critical Section 에 진입하는 횟수는 제한이 있어야 한다.(기아 방지)

동기화의 해결책

Lock : 하드웨어를 통해 프로세스를 제어하는 방법이다. 동시에 공유 자원에 접근하는 것을 막기 위해 임계 영역에 진입하는 프로세스는 Lock을 획득하고 임계 영역에서 빠져나올 때, Lock을 방출한다. 다중 처리 환경에서 시간적인 효율성이 떨어진다는 단점이 있다.

Semaphores(세마포어) : 소프트웨어를 통해 임계 영역 문제를 해결하는 동기화 방법이다. 세마포어는 크게 2가지로 구분할 수 있다. 

카운팅 세마포는 가용한 개수를 가진 자원에 대한 접근 제어용으로 사용하며, 가용한 자원의 개수로 처음에 초기화되고 자원을 사용하면 세마포가 감소하고 방출하면 세마포가 ㅈ으가한다.

이진 세마포는 뮤텍스라고도알려져있다. 이름 그대로 0과 1사이의 값만 가능하며, 다중 프로세스들 사이의 임계 영역 문제를 해결하기 위해 사용하는 방법이다.

세마포어의 방식에는 단점이 존재하는데 Busy Waiting 문제가 발생한다.

초기 세마포어에서는 Spin lock이라고 불리우는 것이 발생했는데, 임계 영역에 접근하기 위해 진입 코드를 계속 반복적으로 실행하면서 CPU시간을 낭비한 것이다. 이를 Busy Waiting이라고 부르며 비효율적인 방법이다. 이 Spin Lock을 해결하기 위해 세마포어에서 임계 영역에 진입을 시도하고 실패한 프로세스에 대해서는 Block 시키고, 임계 영역의 자리가 날 때 다시 호출하는 방식을 사용하면서 Spin lock 문제를 해결하였다.

Deadlock(교착상태)

둘 이상의 프로세스가 임계 영역 진입을 무한정 기다리고 있는 상황에서, 임계 영역에서 실행되는 프로세스는 진입 대기 중인 프로세스가 실행되어야만 빠져나올 수 있는 상황으로 이도저도 못하는 상황을 말한다.

 

 

 

출처 : en.wikipedia.org/wiki/Thread_(computing)