[C#] Thread란? 왜 사용하나?

동키·2024년 12월 18일

C#

목록 보기
8/12

1. 스레드(Thread)란?

  • 스레드는 프로그램이 실행되는 작업의 흐름을 나타냅니다.
  • 하나의 프로그램(프로세스)은 기본적으로 메인 스레드에서 시작하며, 추가 작업을 위해 새로운 스레드를 생성할 수 있습니다.

스레드의 주요 특징

독립적인 실행 흐름

  • 각 스레드는 독립적으로 실행되며, 자신만의 스택 메모리를 사용합니다.

메모리 공유

  • 같은 프로세스 내의 스레드들은 힙 메모리와 전역 변수를 공유합니다.

멀티스레딩

  • 여러 스레드를 사용하면 동시에 여러 작업을 실행하여 프로그램의 응답성과 성능을 향상시킬 수 있습니다.

2.스레드 관련 주요 키워드

Thread

  • 스레드를 생성하고 실행하는 객체.
  • 사용 예제:
// C#
Thread thread = new Thread(() => Console.WriteLine("새로운 스레드 실행"));
thread.Start();

Thread.Join()

  • 특정 스레드가 작업을 완료할 때까지 현재 스레드가 대기.
  • 동기화가 필요할 때 사용.
// C#
thread.Join(); // thread가 완료될 때까지 대기
// thread가 완료 되어야 다음 코드가 실행

lock

  • 공유 자원에 여러 스레드가 동시에 접근하는 것을 방지.
lock (lockObject)
{
    sharedResource++;
}

3. 왜 사용하는가?

스레드를 사용하는 이유는 프로그램이 효율적으로 동시에 여러 작업을 처리할 수 있도록 하기 위해서입니다. 특히, 시간이 오래 걸리는 작업이나 동시다발적인 요청 처리를 필요로 하는 환경에서 스레드는 필수적인 도구입니다.

작업의 병렬 처리

  • 스레드는 병렬 처리를 가능하게 하여 여러 작업을 동시에 실행할 수 있습니다.
  • 특히 멀티코어 CPU 환경에서는 스레드가 서로 다른 코어에서 실행되어 성능이 크게 향상됩니다.

예시: 대규모 데이터 처리

예를 들어, 이미지 처리, 데이터 분석, 암호화와 같은 작업은 계산이 많기 때문에 병렬로 실행하면 속도가 빨라집니다.

using System;
using System.Threading;

class Program
{
    static void Main()
    {
        Thread thread1 = new Thread(() => ProcessData("작업 1"));
        Thread thread2 = new Thread(() => ProcessData("작업 2"));

        thread1.Start();
        thread2.Start();

        thread1.Join();
        thread2.Join();

        Console.WriteLine("모든 작업 완료!");
    }

    static void ProcessData(string taskName)
    {
        Console.WriteLine($"{taskName} 시작...");
        Thread.Sleep(2000); // 데이터 처리 시뮬레이션
        Console.WriteLine($"{taskName} 완료!");
    }
}

결과:

두 작업이 병렬로 실행되므로 처리 시간이 절반으로 줄어듭니다.

작업 1 시작...
작업 2 시작...
(2초 후)
작업 1 완료!
작업 2 완료!
모든 작업 완료!

UI 응답성 유지

  • 스레드는 긴 작업을 백그라운드에서 실행하여 UI가 멈추는 것(Freeze)을 방지할 수 있습니다.
  • 단일 스레드에서 시간이 오래 걸리는 작업을 실행하면 프로그램 전체가 멈춘 것처럼 보입니다.

예시: 파일 다운로드

사용자가 "파일 다운로드" 버튼을 클릭하면 다운로드 작업을 백그라운드 스레드에서 실행하고, 메인 스레드는 계속 UI를 처리합니다.

using System;
using System.Threading;
using System.Windows.Forms;

public class MainForm : Form
{
    private Button downloadButton;

    public MainForm()
    {
        downloadButton = new Button { Text = "파일 다운로드", Dock = DockStyle.Top };
        downloadButton.Click += (sender, e) =>
        {
            Thread thread = new Thread(DownloadFile);
            thread.Start(); // 백그라운드에서 실행
        };

        Controls.Add(downloadButton);
    }

    private void DownloadFile()
    {
        Console.WriteLine("파일 다운로드 중...");
        Thread.Sleep(5000); // 다운로드 시뮬레이션
        Console.WriteLine("다운로드 완료!");
    }

    [STAThread]
    static void Main()
    {
        Application.Run(new MainForm());
    }
}
  • 메인 스레드는 UI를 계속 처리하고, 다운로드는 별도의 스레드에서 실행됩니다.

동시 요청 처리

  • 스레드는 여러 사용자의 요청을 동시에 처리해야 하는 환경에서 매우 유용합니다.
  • 서버와 같은 환경에서 하나의 요청을 하나의 스레드로 처리하여 효율적으로 여러 클라이언트를 지원할 수 있습니다.

예시: 서버 요청 처리

using System;
using System.Threading;

class Program
{
    static void Main()
    {
        for (int i = 1; i <= 3; i++)
        {
            int clientId = i;
            Thread thread = new Thread(() => HandleRequest(clientId));
            thread.Start();
        }
    }

    static void HandleRequest(int clientId)
    {
        Console.WriteLine($"클라이언트 {clientId} 요청 처리 중...");
        Thread.Sleep(3000); // 요청 처리 시뮬레이션
        Console.WriteLine($"클라이언트 {clientId} 요청 완료!");
    }
}

결과:

클라이언트 1 요청 처리 중...
클라이언트 2 요청 처리 중...
클라이언트 3 요청 처리 중...
(3초 후)
클라이언트 1 요청 완료!
클라이언트 2 요청 완료!
클라이언트 3 요청 완료!
  • 각 클라이언트 요청이 독립적인 스레드에서 처리되어 동시에 실행됩니다.

4. 스레드 사용의 장점

성능 향상

  • 멀티코어 환경에서 병렬 처리를 통해 작업 시간이 단축됩니다.

응답성 유지

  • 긴 작업을 백그라운드에서 처리해 UI와 같은 메인 스레드가 계속 실행될 수 있습니다.

동시성 지원

  • 서버나 네트워크 애플리케이션에서 여러 요청을 동시에 처리 가능.

작업 분리

  • 복잡한 작업을 여러 스레드로 나누어 관리 가능.

5.스레드 사용 시 주의사항

데이터 경쟁 상태(Race Condition)

  • 여러 스레드가 공유 데이터에 동시에 접근하면 데이터 불일치가 발생할 수 있습니다.
  • 해결: lock, Monitor, mutex 등으로 동기화 처리.

데드락(Deadlock)

  • 스레드가 서로 자원을 기다리며 무한 대기 상태에 빠질 수 있습니다.
  • 해결: 동기화 순서를 일관되게 유지하거나 타임아웃 설정.

리소스 소비

  • 스레드를 많이 생성하면 시스템 리소스를 많이 소비하므로 적절히 제한해야 합니다.

디버깅 어려움

  • 멀티스레드 환경에서 버그를 재현하거나 해결하는 것이 어렵습니다.
profile
오키동키

0개의 댓글