6강 컴파일러 최적화
[1] 여러 스레드에서 전역 변수 접근하기
program.cs 에서 다음 코딩
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
31
32
33
34
35
36
namespace ServerCore
{
class Program
{
//[2강]
static bool _stop = false;
static void ThreadMain() {
Console.WriteLine("스레드 시작");
while(_stop == false) {
// 어디선가 stop 신호를 해주길 기다린다
}
}
static void Main(string[] args) {
Task t = new Task(ThreadMain);
t.Start();
Thread.Sleep(1000); //1000ms = 1초 / Main 스레드가 1초동안 슬립했다가 깬다
_stop = true;
//=> ThreadMain이 스레드의 _stop bool값이 true가 되었으므로 스레드가 멈출 것임
Console.WriteLine("Stop 호출");
Console.WriteLine("종료 대기중");
t.Wait(); //task는 join과 같은 역할 함
Console.WriteLine("종료 성공");
}
}
}
static bool _stop = false;
- 전역 변수
- Main 스레드에서
_stop
bool값을 true로 만들어주어
ThreadMain
이 멈춤 동작하는 코드
t.Wait(); //task는 join과 같은 역할 함
- 백그라운드 실행을 종료 대기함
결과
1
2
3
4
5
6
7
8
스레드 시작
Stop 호출
종료 대기중
종료 성공
D:\GitRepo\MyGameServer\Server\ServerCore\bin\Debug\netcoreapp3.1\ServerCore.exe(프로세스 9548개)이(가) 종료되었습니다( 코드: 0개).
디버깅이 중지될 때 콘솔을 자동으로 닫으려면 [도구] -> [옵션] -> [디버깅] > [디버깅이 중지되면 자동으로 콘솔 닫기]를 사용하도록 설정합니다.
이 창을 닫으려면 아무 키나 누르세요...
그러나 이는 Debug 모드 한정이다.
실제로 게임이 Release 모드로 바뀌어지면 최적화가 되어지면서
ThreadMain이 종료가 되지 않는다 ✨
[1] Release 모드
결과
1
2
3
스레드 시작
Stop 호출
종료 대기중
- 종료되지 않고 계속 실행되는 모습 …
왜 문제가 일어나는가?! ⇒ 최적화 때문!
✨
여기서 디스 어셈블리 (디버그 - 창 - 디스어셈블리) 를 디버깅 모드에서 열어보면
- while문 안쪽에서
ecx
레지스터의 값이 0이면. je (jump Equal)
: 값이 0이면 while문 처음으로 실행을 돌아가겠다 = while문 반복문을 돌겠다는 코드로 알아서 최적화가 된 것이다- 즉,
1
while(_stop == false){}
이 코드가
1
2
3
if(_stop == false){
while(true){}
}
로 바뀌어 한번 _stop가 false 이면, 영원히 반복문을 돌게 되는 것이다
[2] Release 모드 - 전역변수 최적화 문제 예방하기
1
volatile static bool _stop = false; //전역 변수
- 선언 시
volatile
키워드를 붙여주게 되면, 최적화 하지 말고 그대로 쓰라는 의미가 된다
⇒ 결과) 정상 작동한다 !
[3] c++에서 volatile 키워드
🔥 혼동하지 말자!
c# | c++ | |
---|---|---|
volatile | [1] 최적화 하지 말라 [2] 캐시를 무시하고, 값을 최신으로 가져와라 | [1] 최적화 하지 말라 |
- C#에서 volatile 키워드는 [2] 등을 이유로, 복잡하게 작동하기 때문에, 얘 보다는 다른 키워드를 사용하는 것이 낫다!