컴파일러 최적화(optimizing compiler)는 컴파일러에서 출력되는 실행 프로그램의 효율성을 최적화하는 과정을 말한다.
일반적으로 프로그램의 실행 속도를 최대화하거나 프로그램이 차지하는 메모리의 양을 최소화하기 위해 많이 이용된다.
using System;
using System.Threading;
using System.Threading.Tasks;
namespace SeverCore
{
internal class Program
{
static bool _stop = false;
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();
Console.WriteLine("종료 성공");
}
}
}
Debug 모드에서는 _stop이라는 static 변수에 여러 스레드에서 접근해서 잘 작동하는 것을 확인 할 수 있다.
하지만 게임을 런칭하면 Debug모드가 아닌 Release모드를 사용한다.
하지만 코드를 실행해보면 위와 같이 종료 대기중에서 더 나아가질 못한다.
이는 MainThread가 종료되지 않았기 때문이다.
static void ThreadMain()
{
Console.WriteLine("쓰레드 시작!");
while (_stop == false)
{
}
Console.WriteLine("쓰레드 종료!");
}
release모드로 작성하면 위의 코드에서는 컴파일러 최적화가 일어난다.
그렇게 되면 컴퓨터는 while문을 다음과 같이 변경하여 해석한다.
static void ThreadMain()
{
Console.WriteLine("쓰레드 시작!");
if (_stop == false)
{
while(true) {}
}
Console.WriteLine("쓰레드 종료!");
}
이렇게 되면 _stop의 값이 변경이 된다 해도 while문을 벗어날 수 없기 때문에 쓰레드가 끝이 나지 않게된다.
어떻게 하면 해결 할 수 있을까?
volatile static bool _stop = false;
변수의 맨 앞에 volatile을 적으면 컴파일러에게 최적화 하지 말아달라고 명시적으로 표현할 수 있다.
volatile 키워드는 동시에 실행되는 여러 스레드에 의해 필드가 수정될 수 있음을 나타낸다.
실행시 디버그 모드와 같이 잘 작동함을 확인 할 수 있다.