일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- c# winform
- 플러터
- C# delegate
- c# 윈폼
- docker
- HTML
- Houdini
- dart 언어
- gitlab
- c#
- Algorithm
- Flutter
- Python
- Data Structure
- c언어
- vim
- 깃
- jupyter
- 유니티
- 도커
- 포인터
- C++
- 구조체
- git
- jupyter lab
- github
- c# 추상 클래스
- C언어 포인터
- Unity
- 다트 언어
- Today
- Total
nomad-programmer
[Programming/C#] 스레드의 일생과 상태 변화 본문
.NET 프레임워크는 스레드의 상태를 ThreadState 열거형에 정의해두었다. 다음 표와 같다.
상태 | 설명 |
Unstarted | 스레드 객체를 생성한 후 Thread.Start() 메소드가 호출되기 전의 상태이다. |
Running | 스레드가 시작하여 동작 중인 상태를 나타낸다. Unstarted 상태의 스레드를 Thread.Start() 메소드를 통해 이 상태로 만들 수 있다. |
Suspended | 스레드의 일시 중단 상태를 나타낸다. 스레드를 Thread.Suspend() 메소드를 통해 이 상태로 만들 수 있으며, Suspended 상태인 스레드는 Thread.Resume() 메소드를 통해 다시 Running 상태로 만들 수 있다. |
WaitSleepJoin | 스레드가 블록(Block)된 상태를 나타낸다. 메소드 이름이 WaitSleepJoin인 이유는 스레드에 대해 Monitor.Enter(), Thread.Sleep() 또는 Thread.Join() 메소드를 호출하면 이 상태가 되기 때문이다. |
Aborted | 스레드가 취소된 상태를 나타낸다. Thread.Abort() 메소드를 호출하면 이 상태가 된다. Aborted 상태가 된 스레드는 다시 Stopped 상태로 전환되어 완전히 중지 된다. |
Stopped | 중지된 스레드의 상태를 나타낸다. Abort() 메소드를 호출하거나 스레드가 실행 중인 메소드가 종료되면 이 상태가 된다. |
Background | 스레드가 백그라운드로 동작하고 있음을 나타낸다. 포어그라운드(Foreground) 스레드는 하나라도 살아있는 한 프로세스가 죽지 않지만, 백그라운드는 하나가 아니라 열 개가 살아 있어도 프로세스가 죽고 사는 것에는 영향을 미치지 않는다. 하지만 프로세스가 죽으면 백그라운드 스레드들도 모두 죽는다. Thread.IsBackground 속성에 true 값을 입력함으로써 스레드를 이 상태로 바꿀 수 있다. |
스레드의 상태 변화에는 규칙이 있다. 예를 들어 Aborted 상태의 스레드는 절대 Running 상태로 천이되지 못하고, Running 상태의 스레드는 Unstarted 상태로 바뀔 수 없다.
위 그림에 Background로의 천이하는 과정이 표현되어 있지 않은데, 그 이유는 Background 상태는 그저 스레드가 어떻게 동작하고 있는지에 관한 정보를 나타낼 뿐이기 때문이다.
ThreadState는 Flags 어트리뷰트를 갖고 있다. Flags는 자신이 수식하는 열거형을 비트 필드(Bit Field), 즉 플래그 집합으로 처리할 수 있음을 나타낸다.
비트 필드(bit field)란? |
비트 필드는 원래 C언어 등에서 구조체를 선언할 때 바이트 단위가 아닌 비트 단위로 선언한 필드를 말하며 주로 비트 단위의 플래그를 표현하기 위해 사용한다. C언어가 1970년대 초에 만들어졌고 그 당신의 메모리 가격과 용량을 생각하면 비트 필드가 존재해야 하는 이유가 충분해 보인다. 한 바이트로 0~255까지 표현할 수 있는데 기껏해야 0, 1, 2, 3, ... 7 정도의 값을 갖는 플래그를 표현하려고 한 바이트를 모두 사용하면 메모리 낭비다. C# 언어에서도 비트 필드를 사용할 수 있도록 Flags 어트리뷰트를 .NET 프레임워크에 선언해두었다. |
2020/06/16 - [Programming/C] - [C] 비트 단위 분리
Flags 어트리뷰트를 사용하지 않는 다음과 같은 평범한 열거형은 열거 요소에 대응하는 값들만 표현한다.
// 0, 1, 2, 3
enum MyEnum
{
houdini,
maya,
max,
blender
};
Console.WriteLine((MyEnum)0); // houdini
Console.WriteLine((MyEnum)1); // maya
Console.WriteLine((MyEnum)2); // max
Console.WriteLine((MyEnum)3); // blender
// 열거 요소에 대응하지 못하는 값은 형변환을 시도하여 원래 값으로 표현된다.
Console.WriteLine((MyEnum)4); // 4
Console.WriteLine((MyEnum)5); // 5
반면에 다음과 같이 Flags 어트리뷰트를 갖는 열거형은 요소들의 집합으로 구성되는 값들도 표현할 수 있다.
[Flags]
enum MyEnum
{
houdini,
maya,
max,
blender
};
Console.WriteLine((MyEnum)0); // houdini
Console.WriteLine((MyEnum)1); // maya
Console.WriteLine((MyEnum)2); // max
Console.WriteLine((MyEnum)3); // blender
// Flag 어트리뷰트는 열거형의 요소들의 집합으로 구성되는 값들도 표현할 수 있다.
Console.WriteLine((MyEnum)4); // maya, blender
Console.WriteLine((MyEnum)5); // max, blender
스레드는 동시에 두 가지 이상의 상태를 가질 수 있다. 가령 Suspended 상태이면서도 WaitSleepJoin 상태를 가질 수도 있고, Background 상태이면서 Stopped 상태일 수도 있다. 그래서 ThreadState는 두 가지 이상의 상태를 동시에 표현하기 위해 이 Flags 어트리뷰트가 수식되어 있는 것이다.
ThreadState의 각 요소들 값 확인하는 예제
using System;
using System.Threading;
namespace CSharpExample
{
internal class MainApp
{
private static void PrintThreadState(ThreadState state)
{
Console.WriteLine("{0,-16}: {1}", state, (int)state);
}
static int Main(string[] args)
{
PrintThreadState(ThreadState.Running);
PrintThreadState(ThreadState.StopRequested);
PrintThreadState(ThreadState.SuspendRequested);
PrintThreadState(ThreadState.Background);
PrintThreadState(ThreadState.Unstarted);
PrintThreadState(ThreadState.Stopped);
PrintThreadState(ThreadState.WaitSleepJoin);
PrintThreadState(ThreadState.Suspended);
PrintThreadState(ThreadState.AbortRequested);
PrintThreadState(ThreadState.Aborted);
PrintThreadState(ThreadState.Aborted | ThreadState.Stopped);
return 0;
}
}
}
/* 결과
Running : 0
StopRequested : 1
SuspendRequested: 2
Background : 4
Unstarted : 8
Stopped : 16
WaitSleepJoin : 32
Suspended : 64
AbortRequested : 128
Aborted : 256
Stopped, Aborted: 272
*/
상태 | 십진수 | 이진수 |
Running | 0 | 000000000 |
StopRequested | 1 | 000000001 |
SuspendRequested | 2 | 000000010 |
Background | 4 | 000000100 |
Unstarted | 8 | 000001000 |
Stopped | 16 | 000010000 |
WaitSleepJoin | 32 | 000100000 |
Suspended | 64 | 001000000 |
Aborted | 256 | 100000000 |
Thread 객체의 ThreadState 필드를 통해 상태를 확인할 때는 반드시 비트 연산을 이용해야 한다. ThreadState 열거형이 여러 상태를 동시에 나타낼 수 있도록 만들어져 있기 때문이다.
// Thread 객체의 ThreadState 필드의 값을 확인하는 예제
if (t1.ThreadState & ThreadState.Aborted == ThreadState.Aborted)
Console.WriteLine("스레드 정지됨");
else if (t1.ThreadState & ThreadState.Stopped == ThreadState.Stopped)
Console.WriteLine("스레드 취소됨");
'Programming > C#' 카테고리의 다른 글
[Programming/C#] 스레드 동기화 (Thread Synchronization) (0) | 2020.09.29 |
---|---|
[Programming/C#] 스레드 인터럽트 (Thread Interrupt) (0) | 2020.09.29 |
[Programming/C#] 스레드 임의 종료 (Abort) (0) | 2020.09.28 |
[Programming/C#] 스레드 (Thread) (0) | 2020.09.28 |
[Programming/C#] 객체 직렬화 (Serialization) (0) | 2020.09.28 |