스레드 및 스레딩

업데이트: 2007년 11월

운영 체제에서는 프로세스를 사용하여 실행 중인 다양한 응용 프로그램을 구분합니다. 스레드는 운영 체제에서 프로세서 시간을 할당하는 기본 단위로 두 개 이상의 스레드가 해당 프로세스 내에서 코드를 실행할 수 있습니다. 각 스레드에서는 예외 처리기와 스케줄링 우선 순위, 시스템에서 일정을 잡을 때까지 스레드 컨텍스트를 저장하는 데 사용되는 구조 집합을 유지 관리합니다. 스레드 컨텍스트는 스레드의 CPU 레지스터와 스택 집합을 비롯하여 실행을 다시 시작하기 위해 스레드에서 필요한 모든 정보를 스레드 호스트 프로세스의 주소 공간에 포함합니다.

.NET Framework는 System.AppDomain으로 표시되며 응용 프로그램 도메인이라는 간단한 관리되는 하위 프로세스로 운영 체제 프로세스를 분할합니다. System.Threading.Thread로 표시되는 하나 이상의 관리되는 스레드는 동일한 관리되는 프로세스 내의 하나 이상의 응용 프로그램 도메인에서 실행될 수 있습니다. 각 응용 프로그램 도메인은 단일 스레드로 시작되지만 해당 응용 프로그램 도메인의 코드는 추가 응용 프로그램 도메인과 추가 스레드를 만들 수 있습니다. 따라서 관리되는 스레드가 동일한 관리되는 프로세스 내의 응용 프로그램 도메인 사이를 자유롭게 이동할 수 있습니다. 한 스레드만 여러 응용 프로그램 도메인 사이를 이동하는 경우도 있습니다.

선점 멀티태스킹을 지원하는 운영 체제는 여러 프로세스에서 여러 스레드를 동시에 실행하는 효과를 냅니다. 각 스레드에 프로세서 시간 간격을 차례로 할당하여 프로세서 시간을 필요로 하는 스레드에 사용 가능한 프로세서 시간을 분배하면 가능합니다. 현재 실행 중인 스레드는 해당 시간 간격이 경과되면 일시 중단되고 다른 스레드의 실행이 다시 시작됩니다. 시스템이 한 스레드에서 다른 스레드로 전환될 때 선점 스레드의 스레드 컨텍스트를 저장하고 스레드 큐에 저장된 다음 스레드의 스레드 컨텍스트를 다시 로드합니다.

시간 간격의 길이는 운영 체제와 프로세서에 따라 달라집니다. 각 시간 간격이 짧기 때문에 프로세서가 한 개만 있더라도 여러 스레드가 동시에 실행되는 것처럼 보입니다. 실제로 다중 프로세서 시스템의 경우 실행 가능한 스레드가 사용 가능한 프로세서에 분배됩니다.

다중 스레드를 사용해야 하는 경우

사용자 상호 작용이 필요한 소프트웨어는 다양한 사용자 경험을 제공하기 위해 최대한 빨리 사용자 동작에 반응해야 합니다. 동시에 사용자에게 데이터를 표시하는 데 필요한 계산을 최대한 빨리 수행해야 합니다. 응용 프로그램에서 실행 스레드를 한 개만 사용할 경우 ASP.NET을 사용하여 만든 .NET Framework Remoting이나 XML Web services비동기 프로그래밍과 결합하여 다른 컴퓨터의 처리 시간을 함께 사용함으로써 사용자에 대한 응답성을 향상시키고 응용 프로그램의 데이터 처리 시간을 줄일 수 있습니다. 프로세서 사용이 많은 입출력 작업을 수행할 때 I/O 완료 포트를 사용하여 응용 프로그램의 응답성을 향상시킬 수 있습니다.

다중 스레드의 장점

두 개 이상의 스레드를 사용하는 것은 사용자에 대한 응답성을 향상시키고 동시에 작업을 완료시키기 위해 필요한 데이터를 처리할 수 있는 강력한 기술입니다. 프로세서가 한 개인 컴퓨터의 경우, 다중 스레드에서 사용자 이벤트 사이의 짧은 시간 간격을 이용하여 백그라운드에서 데이터를 처리하면 이러한 효과를 낼 수 있습니다. 예를 들어, 사용자가 스프레드시트를 편집하는 동안 다른 스레드에서 해당 스프레드시트의 다른 부분을 다시 계산할 수 있습니다.

응용 프로그램을 수정하지 않고 두 개 이상의 프로세서를 사용하는 컴퓨터에서 실행하더라도 사용자 만족도가 훨씬 향상됩니다. 단일 응용 프로그램 도메인에서 다중 스레드를 사용하여 다음 작업을 수행할 수 있습니다.

  • 네트워크를 통해 웹 서버 및 데이터베이스와 통신

  • 시간이 오래 걸리는 작업 수행

  • 우선 순위가 다른 작업 구분. 예를 들어, 우선 순위가 높은 스레드는 시간 위험 작업을 관리하고 우선 순위가 낮은 스레드는 다른 작업을 수행합니다.

  • 백그라운드 작업에 시간을 할당하면서 사용자 인터페이스의 응답성

다중 스레드의 단점

가능한 스레드를 적게 사용하여 운영 체제 리소스 사용을 최소화하고 성능을 향상시키는 것이 좋습니다. 스레딩에는 응용 프로그램을 디자인할 때 고려해야 할 리소스 요구 사항과 잠재적 충돌이 있습니다. 리소스 요구 사항은 다음과 같습니다.

  • 프로세스, AppDomain 개체 및 스레드에서 필요한 컨텍스트 정보는 시스템 메모리에 저장됩니다. 따라서 만들 수 있는 프로세스, AppDomain 개체 및 스레드의 수는 사용 가능한 메모리에 의해 제한됩니다.

  • 많은 수의 스레드를 관리하려면 상당한 프로세서 시간이 소비됩니다. 스레드가 너무 많으면 대부분의 스레드에서 작업이 크게 진행되지 못합니다. 현재 스레드가 대부분 한 프로세스에 있으면 다른 프로세스에 있는 스레드의 일정은 자주 잡히지 않습니다.

  • 많은 스레드로 코드 실행을 제어하면 복잡하고 버그가 많이 발생할 수 있습니다.

  • 스레드를 삭제하려면 삭제 후 발생하게 될 문제와 그 처리 방법에 대해 알아야 합니다.

리소스에 공유 액세스를 제공하면 충돌이 생길 수 있습니다. 충돌을 피하려면 공유 리소스에 대한 액세스를 제어하거나 동기화해야 합니다. 같거나 다른 응용 프로그램 도메인에서 액세스를 제대로 동기화하지 못하면, 교착 상태 또는 경쟁 상태와 같은 문제가 발생할 수 있습니다. 교착 상태에 빠지면 두 개의 스레드가 서로 완료되기를 기다리면서 모두 응답을 멈추게 되고, 경쟁 상태에 빠지면 두 이벤트의 타이밍에 대한 예기치 못한 심각한 종속성으로 인해 비정상적인 결과가 발생할 수 있습니다. 시스템에서 다중 스레드 간의 리소스 공유를 조정하는 데 사용되는 동기화 개체를 제공합니다. 스레드 수를 줄이면 리소스를 동기화하기가 더 쉽습니다.

동기화가 필요한 리소스는 다음과 같습니다.

  • 시스템 리소스(예: 통신 포트)

  • 여러 프로세스에서 공유하는 리소스(예: 파일 처리)

  • 다중 스레드에서 액세스하는 단일 응용 프로그램 도메인의 리소스(예: 전역, 정적, 인스턴스 필드)

스레딩 및 응용 프로그램 디자인

일반적으로 ThreadPool 클래스를 사용하면 다른 스레드를 차단하지 않고 작업 스케줄링이 필요 없는 간단한 작업에 대해 여러 스레드를 매우 쉽게 처리할 수 있습니다. 하지만 다음과 같이 사용자 고유의 스레드를 만들어야 하는 여러 가지 이유가 있습니다.

  • 작업에 특정 우선 순위를 지정해야 할 경우

  • 실행 시간이 오래 걸려서 다른 작업을 차단해야 할 경우

  • 모든 ThreadPool 스레드는 다중 스레드 아파트에 있는데 일부 스레드를 단일 스레드 아파트에 두어야 하는 경우

  • 스레드에 안정적인 ID가 필요할 경우. 예를 들어, 스레드를 중단하거나 일시 중단, 이름으로 검색할 경우 전용 스레드를 사용해야 합니다.

  • 사용자 인터페이스와 상호 작용하는 백그라운드 스레드를 실행해야 하는 경우 .NET Framework 버전 2.0에서는 이벤트를 사용하여 사용자 인터페이스 스레드로 크로스 스레드 마샬링과 통신하는 BackgroundWorker 구성 요소를 제공합니다.

스레딩 및 예외 사항

스레드에서는 예외가 처리됩니다. 일반적으로 백그라운드 스레드를 포함한 스레드의 처리되지 않은 예외로 인해 프로세스가 종료됩니다. 다음은 이 규칙의 세 가지 예외 사항입니다.

  • Abort가 취소되었으므로 스레드에서 ThreadAbortException이 throw됩니다.

  • 응용 프로그램 도메인이 언로드 중이므로 AppDomainUnloadedException이 throw됩니다.

  • 공용 언어 런타임 또는 호스트 프로세스에서 스레드를 종료합니다.

자세한 내용은 관리되는 스레드의 예외를 참조하십시오.

참고:

.NET Framework 버전 1.0 및 1.1에서 공용 언어 런타임은 스레드 풀 스레드 등에서 일부 예외를 포착합니다. 이렇게 하면 응용 프로그램 상태가 손상되어 결국 응용 프로그램이 중단될 수 있고, 이에 따라 디버깅이 어려워질 수 있습니다.

참고 항목

개념

다중 스레딩을 위한 데이터 동기화

관리되는 스레드 풀

참조

ThreadPool

BackgroundWorker