[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 컴파일러 최적화

참치와돌고래·2022년 8월 12일
0

다음 코드를 살펴보자.

//static: 모든 쓰레드가 공유함. 
        static bool _stop = false;
        static void ThreadMain()
        {
            Console.WriteLine("쓰레드 시작");
            while (_stop == false)
            {
                //stop신호를 기다림 
            }
            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로 바꾸어 무한 루프를 멈춘 다음 종료하는 코드이다. 실제로도 우리가 의도한 대로 잘 돌아간다. 그러나 디버그 모드에서 릴리즈 모드로 변환 후 실행시 의도적으로 실행되지 않는 현상이 발생한다. 이유인 즉슨

while(_stop==false){
}//기존 우리가 작성한 코드를

if(_stop==false){
	while(true){
    }
}//컴파일러가 다음과 같이 바꾸었기 때문.

...이라고 한다. 실제로 두 코드는 논리 상으론 정확하다. 다만 컴파일러가 멀티 쓰레드 환경임을 인지 못하고 멋대로 최적화하다가 오류가 났을 뿐.
이를 간단하게 해결하려면

volatile static bool _stop=false 

로 _stop 변수 앞에 volatile를 붙여주면 된다. Release 모드 시 최적화를 하지 말라는 뜻으로 알면 될 듯하다.

volatile를 이용하는 방법 자체보다는 Debug 모드일 때와 Release 모드일 때 멀티쓰레드 환경에선 이러한 이유 때문에 오류가 날 수 있다는 점을 배운 시간이였다.

0개의 댓글