반응형
메모리 최적화 예시
static int x = 0;
static int y = 0;
static int r1 = 0;
static int r2 = 0;
static void Thread_1()
{
y = 1;
r1 = x;
}
static void Thread_2()
{
x = 1;
r2 = y;
}
static void Main(string[] args)
{
int count = 0;
while(true)
{
count++;
x = y = r1 = r2 = 0;
Task t1 = new Task(Thread_1);
Task t2 = new Task(Thread_2);
t1.Start();
t2.Start();
Task.WaitAll(t1, t2);
if (r1 == 0 && r2 == 0) break;
}
Console.WriteLine($"{count}번 만에 빠져나옴");
}
- 다음 코드를 실행하면, while이 빠져나와질까?
- 놀랍게도 빠져나와진다!
- 하드웨어도 최적화를 하고 있기 때문이다
- x = 1과 r2 = y가 아무런 관련이 없기 때문에, 하드웨어가 마음대로 실행 순서를 바꾼 것
- 싱글 쓰레드 환경에선 문제가 없지만, 멀티 쓰레드에선 문제가 됨
메모리 배리어
코드 재배치 억제
static void Thread_1()
{
y = 1; //w
Thread.MemoryBarrier(); //코드 사이에 장벽을 설정해서, 순서 바꾸지 말라고 강제
r1 = x; //r
}
static void Thread_2()
{
x = 1; //w
Thread.MemoryBarrier();
r2 = y; //r
}
- 다음과 같이 Thread.MemoryBarrier()를 활용하여, 코드의 순서를 바꾸지 못하도록 강제할 수 있음
- Store/Load 모두 막는다
가시성
- 1번 직원이 주문을 받은 것을, 다른 직원들도 볼 수 있나?
- 즉, 주문 현황에 주문 받은것을 저장해야함
- 다른 직원들은, 주문현황에서 가져와야 함
- MemoryBarrier가 가시성도 해결해준다!
- 순서 억제 뿐 아니라 바로바로 주문현황에 올려줌
- MemoryBarrier는 아토믹이나 락 등에 내부적으로 구현된 경우가 많음
다른 예제
int _answer;
bool _complete;
void A()
{
_answer = 123; //w
Thread.MemoryBarrier();
_complete = true; //w
Thread.MemoryBarrier();
}
void B()
{
Thread.MemoryBarrier();
if(_complete)
{
Thread.MemoryBarrier();
Console.WriteLine(_answer); //r
}
}
- 마지막과 처음의 메모리 배리어는 무엇인가?
- 이번에는 store가 연속적으로 두 번 일어남
- 쓸 때마다, 동기화 작업을 직접 해주는 것
- B에서는 읽기 전에 일단 동기화를 하고
- if문 안에서도 읽기 전에 동기화 먼저 확실하게 해주고 WriteLine을 진행하는 것
반응형
'C# > 네트워크' 카테고리의 다른 글
[C#][서버] Lock 기초 (0) | 2024.06.02 |
---|---|
[C#][서버] Interlocked (0) | 2024.06.01 |
[C#][서버] 캐시 이론 (0) | 2024.05.31 |
[C#][서버] 기본 멀티쓰레드 프로그래밍 (0) | 2024.05.30 |
[C#][서버] 서버 개론, 멀티쓰레드 개론 (0) | 2024.05.30 |