2022. 2. 14. 00:00ㆍCSharp/Advance
스레딩을 통해 코드의 병렬 실행을 지원한다.
스레드는 다른 스레드와 동시에 실행할 수 있는 독립적인 실행 경로이다.
기본사용법
아래 내용을 실행하면 processor 에 따라 다르겠지만 중간 중간에 11112222211111 같은 형태의 output 이 된다.
즉 Thread(Write).Start 와 Basic() 내의 for(..) 문이 다른 Thread 상에서 동시에 진행되는 것이다.
public void Basic()
{
Thread t = new Thread(Write);
t.Start();
for (int i = 0; i < 1000; i++) Console.Write("1");
}
private void Write()
{
for (int i = 0; i < 1000; i++) Console.Write("2");
}
t.Start() 에 F9 를 통해 break point 를 걸고
Write() 안의 for 문에도 F9 를 통해 break point 를 걸어보자
그 후 F5 를 통해 실행하고 (Debugging 실행)
Debug-->Windows-->Threads (C++ 환경기준 Ctrl+Alt+H) 를
실행해보자 아래와 같은 화면이 추가된다.
현재 Basic() 함수내의 내용은 11244 (1) 의 Main Thread (프로그램의 논리가 흐르는 주 thread ) 에서 실행된다.
Write() 함수 내의 내용은 Thread 에 의해 27288 (10) 의 새로운 Worker Thread <No Name> 가 생성된다.
즉 둘은 거의 동시(cpu core 가 여러개라고 가정할때) 에 실행되는 것을 알수 있다.
**실행할때마다 ID 는 변합니다.**
아래 이미지와 같다. 다른점은 우리는 x, y 라는 값 대신에 1,2 라는 값을 사용했다.
동기화
아래와 같이 int i 라는 변수를 공유하고 있는 Thread 코드가 있다고 하자
private int i = 0;
public void Basic()
{
Thread t = new Thread(Worker);
t.Start();
Worker();
}
private void Worker()
{
for (; i < 1000; i++) Console.Write($"{i} ");
}
//output
0 0 2 3 4 5 6 7 8 9 10 1.....
output 을 확인해보면 i 의 값이 순서대로 진행되지 않고 ramdom 하게 변경되는걸 볼수 있다.
이것은 한 Thread 가 i 에 접근하여 i 값을 변경 하려는 동안
다른 Thread 가 i 에 접근하여 i 값을 변경 하려는 작업이 동시에 일어나서 생기는 일이다.
이럴경우는 lock 을 통해 i 값을 동기화 해야 한다.
다음과 같이 코드를 수정하면 정상적으로 처리되게 된다.
private int i = 0;
private static readonly object locker = new object();
public void Basic()
{
Thread t = new Thread(Worker);
t.Start();
Worker();
}
private void Worker()
{
lock (locker)
{
for (; i < 1000; i++) Console.Write($"{i} ");
}
}
Barrier
여러 단계로 구성된 알고리즘에서 사용 하는 쓰레드 동기화 객체
private Barrier _barrier = new Barrier(5, barrier => Console.WriteLine());
public void Barrier()
{
for (int i = 0; i < 5; i++)
{
int j = i;
new Thread(() => Count(j)).Start();
}
}
/// <summary>
/// barrier 은 생성된 모든 Thread 가 SignalAndWait() 한 부분까지
/// 처리 하기 전까지 다음 라인으로 진행되지 않는다.
/// </summary>
/// <param name="i"></param>
private void Count(int i )
{
Console.WriteLine(i + ": get from Database ");
_barrier.SignalAndWait();
Console.WriteLine(i + ": send to WebServer ");
_barrier.SignalAndWait();
Console.WriteLine(i + ": delete from Database ");
_barrier.SignalAndWait();
}
// output
1: get from Database
0: get from Database
2: get from Database
3: get from Database
4: get from Database
4: send to WebServer
1: send to WebServer
0: send to WebServer
2: send to WebServer
3: send to WebServer
0: delete from Database
3: delete from Database
4: delete from Database
1: delete from Database
2: delete from Database
관련영상
'CSharp > Advance' 카테고리의 다른 글
Parallel Programming (TPL Dataflow) (0) | 2022.02.16 |
---|---|
Parallel Programming (TPL) (0) | 2022.02.15 |
범위와 인덱스 그리고 슬라이싱 (Range, Index and Slicing) (0) | 2022.02.11 |
LINQ Join Operators (조인연산자) (0) | 2022.02.10 |
LINQ Aggregator Operators (집계연산자) (0) | 2022.02.09 |