1. 쓰레드 구현
using System;
using System.Threading;
using System.Threading.Tasks;
namespace ServerCore
{
class MainClass
{
static bool _stop = false; // volatile = 최적화 노!, 캐시 무시하고 최신 값 읽게 함
static void ThreadMain()
{
Console.WriteLine("쓰레드 시작 !");
while (_stop == false)
{
}
Console.WriteLine("쓰레드 종료 !");
}
static void Main(string[] args)
{
Task t = new Task(ThreadMain);
t.Start();
Thread.Sleep(1000);
_stop = true;
Console.WriteLine("Stop 호출 ");
Console.WriteLine("종료 대기 중");
t.Wait(); // 종료 대기 = thread join
Console.WriteLine("종료 성공");
}
}
}
ThreadMain 이라는 메서드를 가진 Task 를 실행시킨다. 1초 후에 _stop 변수를 true 로 바꿔주어 실행 중이던 쓰레드가 종료되도록 하는 코드이며, Debug 모드 컴파일러에서는 정상 동작하게 된다.
하지만 Release 모드로 컴파일을 하게되면 코드에서 동일한 동작이지만 코스트가 적은 내용으로 최적화를 진행하게 된다.
while (_stop == false)
{
}
// release 모드로 최적화 하면 아래와 같이
if (_stop == false)
{
while (true) { }
}
위에서 _stop 이 false 일 경우 무한 반복중이던 코드가 if ~ while 문으로 변경되면서 이후에 _stop 값이 변경 되더라도 무한 반복이 진행되며 빠져나올 수 없게 된다.
이럴 때 volatile 문법으로 _stop 변수에 관련해서는 최적화 하지말고, 캐시를 무시하고 최신 값을 읽도록 지정할 수 있지만 잘 사용하지 않는다고 한다. 이러한 경우에 대해 메모리 베리어 등을 사용하게 된다.
즉 쓰레드로 개발 시 컴파일러에 관한 문제 등이 있어 복잡해진다는 것을 알게 되었다.