개요

개발자가 아니더라도 컴퓨터에 관심이 있는 사람들은 CPU를 검색했을때  듀얼코어 4쓰레드, 쿼드코어 8쓰레드
등 쓰레드란 말을 익숙하게 들어보셨을겁니다. 프로그래밍에서 쓰레드란 용어는 CPU의 성능을 불리우는 쓰레드와 동일합니다.
이번 포스팅을 하게 된 계기는 " 데이터를 효율적으로 다룰 수 있는 방법이 어떤게 있을까? "라는 생각을 하였습니다.
그 중 데이터를 병렬처리하는 방법중 하나인 쓰레드 그리고 쓰레드를 포함하는 프로세스에 대해 알아보며 학습한 자료를 기록하기위해 작성하게 되었습니다.

 

 

 

프로세스(Process)의 정의

프로세스는 실행중인 프로그램을 나타내는 하나의 단위입니다.

프로세스는 운영체제에서 자원(메모리)을 할당받아 실행되는 프로그램이며, 위의 첨부된 사진처럼 하나의 프로세스 안에서 실행코드, 메모리공간, 스레드 등의 자원들을 가지고 있습니다.

 

프로세스의 특징

  1. 프로세스는 여러개의 프로세스를 가질 수 있으며, 각각 독립적인 실행 환경을 가지고 있다.
  2. 독립적인 실행 환경을 통해 프로세스는 서로 다른 물리적 메모리 공간을 보유하고 있다.
  3. 프로세스들은 서로의 자원을 공유하지 않는다

 

 

쓰레드(Thread)의 정의

쓰레드(Thread)란 동시에 실행될 수 있는 작업의 단위를 나타내는 하나의 객체입니다.

프로그램이 실행시 하나의 프로세스가 생성되며, 쓰레드는 생성된 프로세스의 내부에 생성됩니다.

또한, 쓰레드는 하나의 프로세스 안에서 여러개의 쓰레드가 존재할 수 있습니다. 이것을 멀티 쓰레드라고 합니다.

쓰레드는 각각 고유의 스택 영역을 보유하고 있으며, 프로세스 내부의 쓰레드끼리는 프로세스 내부의 자원을

공유하여 사용합니다.

 

쓰레드의 특징

  1. 쓰레드는 프로세스 내부에 존재하며, 여러개의 쓰레드를 가질 수 있다.
  2. 프로세스 내부의 쓰레드끼리는 서로의 자원을 공유한다.
  3. 여러 쓰레드가 공유하는 자원에 동시에 접근하는 경우, 동기화 문제가 발생할 수 있다.
  4. 쓰레드 간의 전환은 컨텍스트 스위칭(Context Switching)이라고 하는 작업이 필요하며, 오버헤드를 발생시킨다.
  5. 쓰레드간에 서로 자원을 공유하지만, Thread Safe하지 않을시 데이터 불일치성이 생기며 이를 Lock이나 synchronized 예약어를 사용해야하는 작업이 필요하다.

 

프로세스 VS 쓰레드

프로세스와 쓰레드의 차이를 예시를 들어 설명하자면 쓰레드는 하나의 실, 프로세스는 그 실들이 뭉친 실타래 라고 할 수 있습니다.

개발자가 쓰레드를 생성시 하나의 실(쓰레드)가 생성되며 또한 실을 자를 수 있듯이, 쓰레드는 종료 될 수 있습니다.

이 실(쓰레드)들이 여러개면 멀티쓰레드, 그리고 이 실들의 집합체를 실타래(프로세스) 라고 합니다.

쓰레드는 여러개의 쓰레드를 보유할 수 있으며, 서로의 자원을 공유하는 장점을 가지고 있습니다.

자원을 공유하여 사용한다는건, 병렬처리를 할 수 있다는 것이며 이것은 곧 더 빠른 데이터 처리를 할 수 있다는것을 의미합니다.

프로세스 또한 여러개의 프로세스를 가질 수 있지만, 쓰레드와 다르게 서로의 자원을 공유하지 않습니다.

이러한 자원의 공유가 없다는 점과, 프로세스는 생성 시 물리적 메모리를 운영체제에 따라 32MB ~ 64MB를 

차지하게 되며, 쓰레드는 1MB를 차지하는 물리적 차이를 가지고 있습니다.

 

멀티쓰레드의 장점

  • 멀티쓰레딩을 통해 여러개의 쓰레드가 동시에 작업을 수행하므로 병렬 처리를 구현 할 수 있다.
  • 멀티쓰레드는 여러 쓰레드가 같은 프로세스 내에서 실행 되며, 프로세스 내부의 자원을 공유한다.
  • 쓰레드는 프로세스에 비해 물리적 메모리를 덜 차지하며, 컨텍스트 스위칭 시 오버헤딩의 비용이 낮다.

멀티쓰레드의 단점

  • 프로세스 내부의 공유하는 자원에 동시에 접근하는 경우 동기화(Synchoronization) 문제가 발생 할 수 있다.
  • 멀티 쓰레드를 사용하여 프로그래밍 시 복잡성이 증가하며 단일 쓰레드보다 디버깅이 어렵다.
  • 여러 쓰레드가 하나의 자원에 동시에 접근하는 경우 값이 예상치 못한 값이 나올 수 있다. (안전성이 부족하다)
#include <iostream>
#include <thread>
#include <atomic>

class ExampleCoadThread {
public:
    static std::atomic<int> Count; // 스레드 안전한 정수

    void operator()() {
        for (int i = 0; i < 5000; i++) {
            Count++;
        }
    }
};

// 정적 변수 초기화
std::atomic<int> ExampleCoadThread::Count(0);

int main() {
    ExampleCoadThread threadTask; 

    std::thread thread1(threadTask);
    std::thread thread2(threadTask);

    thread1.join();
    thread2.join();

    std::cout << "Thread Sum : " << ExampleCoadThread::Count << std::endl;

    return 0;
}

단점을 코드블럭으로 예시를 해보겠습니다.

static으로 선언한 Count의 값을 10000까지 증감시킬려면 기본 단일 쓰레드에서는 run메서드를 2번만 호출하거나,

i의 boolean값을 10000으로 하면 되는 경우입니다.

멀티스레드를 사용하여 코딩을 할시에는 기본 단일스레드와 유사하나 exampleCoadThread클래스의 객체를 2개 생성하며main메서드에서 각각 쓰레드들의 종료가되었는지 확인하는 예외처리가 필요합니다.

또한 Thread Safe하지않아 원하는 값이 안나오니 동기화 혹은 Lock을 걸어야 하는 경우가생깁니다.

이러한 간단한 코드블럭에도 복잡성이 증가하며, 동기화 혹은 Lock을 지정하지 않아 안전성이 불안정한 단점을 예시로 들 수 있습니다. 

 

 

 

정리 및 느낀점

 

정리

프로세스는 프로그램이 실행시 운영체제에서 자원을 할당받아 생성되며, 다수의 프로세스를 생성할 수 있다.

쓰레드는 프로세스 내부에 생성되며, 다수의 쓰레드를 가질 수 있다. 

프로세스는 서로 자원을 공유하지 않지만, 쓰레드는 서로의 자원을 공유 할 수 있다.

프로세스는 32MB ~ 64MB의 물리적 메모리공간을 차지하며, 쓰레드는 1MB의 메모리 공간을 차지한다.

└ 프로세스와 쓰레드의 메모리 크기는 OS와 사용언어와 라이브러리 등에 따라 다릅니다. 또한 최대 메모리 크기는 32비트 아키텍처, 64비트 아키텍처에 따라 다르며, 64비트 아키텍처가 더 큰 스택의 크기를 가지기 때문에 최대 메모리 크기가 64비트가 더 높습니다. 

멀티쓰레드는 자원을 공유받아 병렬처리를 할수있어 단일 쓰레드에 비해 처리 속도가 빠르지만, 하나의 데이터에

여러개의 쓰레드가 동시 접근 할 경우 동기화 문제 및 안전성의 문제가 있다.

+ Recent posts