02_Thread와 Task

7072 단어 CC

✔️프로세스와 스레드

오늘날 운영체제는 여러 프로세스(Process)를 동시에 실행할 수 있다.

ex_유튜브로 노래를 들으며 동영상 편집을 할 수 있다.

프로세스도 한번에 여러가지 작업이 가능하다

ex_VScode에서 코드를 작성하면서 동시에 잘못된 문법을 체크해 붉은색으로 표시해준다.

🤷‍♀️프로세스_Process

프로세스는 실행 파일이 실행되어 메모리에 적재된 인스턴스.
예를 들어 워드가 실행 파일이라면, 이 실행 파일에 담겨 있는 데이터와 코드가 메모리에 적재되어 동작하는 것이 프로세스이다.
프로세스는 반드시 하나 이상의 스레드로 구성되는데, 스레드는 운영체제가 CPU시간을 할당하는 기본단위이다.

  • 운영체제와 프로세스, 프로세스와 스레드

  • 단일 스레드: "프로세스3"처럼 한 번에 한 가지 일만 하는 것

  • 멀티 스레드: "프로세스1","프로세스2","프로세스3"처럼 여러 개의 스레드를 가져 다중 작업을 하는 것

✏️멀티 스레드의 장단점

  • 장점
    1. 대화형 프로그램에서 멀티 스레드를 이용하면 응답성을 높일 수 있다.

    단일 스레드를 사용하는 프로그램을 만들었다.
    이 프로그램에서 파일 복사만 30분이 걸린다.
    사용자가 파일 복사를 취소하고 싶어도 프로그램은 사용자에게 반응하지 않아서 복사를 취소할 수가 없다.
    결국 작업 관리자를 이용해서 강제로 프로세스를 종료시켜야했다.

    이 프로그램에서 사용자와의 대화를 위한 스레드를 하나 더 추가한다면 파일 복사를 하면서도 사용자로부터 명령을 입력받을 수 있다.
  1. 멀티 프로세스 방식에 비해 멀티 스레드 방식이 자원 공유가 쉽다.

    멀티 프로세스는 GUI가 없는 웹 서버 같은 서버용 애플리케이션에서 많이 취하는 구조이다.
    프로세스끼리 데이터를 교환하려면 소켓이나 공유 메모리 같은 IPC(Inter Process Communication)를 이용해야하는데 이는 꽤나 번거롭다.
    반면 멀티 스레드 방식에서는 그저 스레드끼리 코드 내의 변수를 같이 사용하는 것만으로도 데이터 교환을 할 수가 있다.

  • IPC를 통한 프로세스 간의 데이터 교환
  • 변수를 이용한 스레드 간의 데이터 교환
  1. 경제성이 좋다.
    프로세스를 띄우기 위해 메모리와 자원을 할당하는 작업은 비용이 비싸다.
    스레드를 띄울 때, 이미 프로세스에 할당된 메모리와 자원을 그대로 사용하므로 메모리와 자원을 할당하는 비용을 지불하지 않아도 된다.
  • 단점
  1. 구현하기가 매우 까다롭다.
    멀티 프로세스 기반의 소프트웨어는 여러 개의 자식 프로세스 중 하나에 문제가 생기면 그 자식 프로세스 하나가 kill되는 게 끝.
    멀티 스레드 기반의 소프트웨어는 자식 스레드 중 하나에 문제가 생기면 전체 프로세스에 영향이 발생한다.

  2. 스레드를 너무 많이 사용하면 오히려 성능이 더 저하된다.
    스레드가 CPU를 사용하기 위해서는 작업 간 전환(context swtiching)을 해야하는데, 이 작업이 비용을 많이 소모한다.
    많은 스레드가 너무 자주 작업 간 전환을 수행하면 애플리케이션이 실제로 일하는 시간에 비해 작업 전환에 사용하는 시간이 커져 성능이 저하된다.

👨‍💻C#에서 스레드 하기

C#은 .NET에서 스레드를 제어하는 클래스 System.Threading.Thread를 제공한다.

  • 클래스를 사용하는 방법
  1. Thread의 인스턴스를 생성한다. 이때 생성자의 인수로 스레드가 실행할 메소드를 넘긴다.
  2. Thread.Start() 메소드를 호출하여 스레드를 시작한다.
  3. Thread.Join() 메소드를 호출하여 스레드가 끝날 때까지 기다린다.
//스레드가 실행할 메소드
static void DoSometing() {
	for(int i = 0 ; i < 5 ; i++){
    	Console.WriteLine("DoSomething : {0}",i);
	}
}
static void Main(string[] args){
	//Thread인스턴스 생성 및 인수로 메서드를 넘긴다.
    Thread t1 = new Thread(new ThreadStart(DoSomething)); 
    //스레드 시작
    t1.Start();
    //스레드의 종료 대기
    t1.Join();
}

위 코드에서 생성한 스레드가 적재되는 시점은 인스턴스를 만드는 것이 아닌 t1.Start()이다.
생성한 스레드를 실행하면 메인 프로세스에서 나와 작업을 수행하고 Join()메소드가 반환되는 시점에서 다시 프로세스로 합류한다.

  • 스레드 상태_ThreadState

  • ThreadState가 Flags 속성을 가지고 있다.
    Flags는 자신이 수식하는 열거형을 비트 필드,즉 플래그 집합으로 처리할 수 있다.

✏️스레드 간의 동기화

애플리케이션을 구성하는 각 스레드는 여러 가지 자원을 공유한다.
파일 핸들, 네트워크 커넥션, 메모리에 선언한 변수를 통해 공유를 한다.

동시에 여러 작업을 할 때는 멀티 스레드를 사용하는 것이 멀티 프로세스보다 시스템 자원(메모리)를 더 적게 사용한다.

스레드가 프로세스에 비해 탁월한 기능을 가지고 있어보이지만, 스레드에도 단점이 있다.
바로 동기화(Sysnchronize)이슈이다.

스레드1이 공유 자원 내의 어떤 데이터를 조작한다.
스레드2에게 제어권을 넘겨준 이후 스레드2가 그 데이터를 번경한다.
스레드1이 다시 제어권을 받아 남은 작업을 계속할 때 원하지 않는 결과가 나온다.

  • 은행 출금 동기화 문제

이러한 문제를 해결하기 위해 특정 자원에 접근하지 못하도록 Lock을 걸어 동기화 문제를 해결한다.
다양한 동기화 기법을 운영체제가 제공한다.
하지만 스케줄링을 운영체제가 자동으로 해주지 않고, 프로그래머가 적절한 기법을 선택하여 직접 구현해야한다.

cf_스케줄링 기법

😎예상 면접 질문

  • 멀티 스레드의 장단점이 무엇인가?

    장점 : 응답성 향상, 자원공유 용이, 경제성
    단점 : 동기화 이슈, 잦은 스위칭시 비용 증가

  • Context Switching이 왜 필요한가요?

    현재 진행하고 있는 Task(Process, Thread)의 상태를 저장하고 다음 진행할 Task의 상태 값을 읽어 적용하는 과정을 말합니다.

  • 프로세스와 스레드간에 어떤 것이Context Switching에 비용이 더 드는가요?

    Context Switching 비용은 Process가 Thread보다 많이 듭니다.
    Thread는 Stack 영역을 제외한 모든 메모리를 공유하기 때문에
    Context Switching 발생시 Stack 영역만 변경을 진행하면 됩니다.

좋은 웹페이지 즐겨찾기