8강 메모리 베리어
[1] 하드웨어 최적화
컴파일러도 최적화를 하지만, 하드웨어도 최적화를 한다
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
37
38
39
40
41
42
43
44
45
46
47
48
class Program
    {
        static int x = 0;
        static int y = 0;
        static int r1 = 0;
        static int r2 = 0;
        //하드웨어 최적화
        static void Thread_1() {
            /*[1]*/y = 1; //store y
            /*[2]*/r1 = x; // load x
        }
        static void Thread_2()
        {
            /*[3]*/x = 1; //store x
            /*[4]*/r2 = y; //load y
        }
        static void Main(string[] args) {
            int cnt = 0;
            while (true)
            {
                cnt++;
                x = y = r1 = r2 = 0; //모두 0을 넣는다
                Task t1 = new Task(Thread_1);
                Task t2 = new Task(Thread_2);
                t1.Start();
                t2.Start();
                Task.WaitAll(t1, t2);
                //이부분이 중요!
                //[1][2][3][4] 경우를 순서대로 조합해보아도 둘다 0이 되는 경우는 존재하지 않는다!
                //그러나 실행해보면 끝이난다
                if (r1 == 0 && r2 == 0) break;
            }
            Console.WriteLine($"{cnt} 번 만에 빠져나옴");
        }
    }
- 2개의 스레드의 다음 코드
 - [1] 
y = 1; - [2] 
r1 = x; - [3] 
x = 1; - [4] 
r2 = y; if (r1 == 0 && r2 == 0) break;- [1][2][3][4] 경우를 순서대로 조합해보아도 둘다 0이 되는 경우는 존재하지 않지만, break로 종료가 된다!
 
⇒ 이유가 뭘까??
⇒ 하드웨어가 최적화를 하기 때문이다
하드웨어가 코드의 순서대로 실행하지 않고 스레드내의 코드의 순서를 바꾸기 때문이다
- 최적화의 코드의 순서
[2]
r1 = x;4]
r2 = y;👇
[1]
y = 1;[3]
x = 1;
### Store과 Load
y = 1;그냥 **실제 값을 넣는 것r1 = x;변수에서 값을 끄집어 내는 것- x에서 값을 끄집어내서 할당하고 있음
 
 
[2] 메모리 베리어
[1] 하는 이유
- 코드 재배치 억제 ([1]과 같은 경우)
 - 가시성이 좋다
 
[2] 메모리베리어 작동
메모리 베리어 하는 법
Thread.MemoryBarrier()
1
2
3
4
5
static void Thread_1() {
            /*[1]*/y = 1; //store y
            Thread.MemoryBarrier(); //메모리 베리어
            /*[2]*/r1 = x; // load x
        }
1
2
3
4
5
6
7
static void Thread_2()
        {
            /*[3]*/x = 1; //store x
            Thread.MemoryBarrier(); //메모리 베리어
            /*[4]*/
            r2 = y; //load y
        }
[3] 메모리 베리어의 종류
[1] Full Memory Barrier 🌟
- 메모리에서 Store , Load를 둘다 막는다
 
[2] Store Memory Barrier
- Store만 막는다
 
[3] Load Memory Barrier
- Load만 막는다
 
가시성 (메모리베리어의 작동 원리)
- 메모리 베리어는 가시성이 좋다
 
[1] 메모리 베리어의 역할
스토리 텔링으로
🧑직원이 주문 받은 내역을 🔖주문현황에 옮기고, 🧑🏻다른 직원이 그 주문현황을 바탕으로 자신의 📘수첩을 업데이트 하는 행위와 같다
⇒ 값을 최신의 값으로 따끈따근하게 💛업데이트💛 하는 것과 같다 (가시성에 도움!)
Thread.MemotyBarrier();을 쓴 코드 윗단의 가시성을 보장한다
⇒ 정리하면, 메모리 베리어는 중앙 메모리에서 변수의 실제 현재 값을 가져오는 것이다
volatile도 메모리 베리어 의 역할을 간접적으로 하고 있는 것이다- Lock, 아토믹도 간접적이다
 
메모리 베리어 예제
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int ans;
bool complete;
void A(){
	ans = 123;
	Thread.MemoryBarrier();
	complete = true;
	Thread.MemotyBarrier();
}
void B(){
	Thread.MemotyBarrier();
	if(complete){
		Thread.MemotyBarrier();
		Console.WriteLine(ans);
	}
}
complete = true; Thread.MemotyBarrier();- 코드가 끝난 부분에도 메모리 베리어를 해줌으로써 가시성을 확실히 보장함
 - 원하는 결과가 나올 것임
 
…