📄 메모리 배리어
메모리 배리어는
[코드 재배치 억제] 캐시에 의한 재배치, CPU 파이프라인에 의한 코드 재배치에 의해 멀티스레드환경에서 의도하지 않은 연산 결과를 억제할 수 있습니다.
[가시성 보장] 또한 특정 스레드에서 공유 메모리 자원에 대한 값을 변경하고, 다른 스레드가 같은 공유 메모리에 접근할 때, 특정스레드가 변경해놓은 값을 읽어올 수 있도록 합니다.
📑 예제
namespace ServerCore
{
class Program
{
static int x = 0;
static int y = 0;
static int r1 = 0;
static int r2 = 0;
static void Thread1()
{
y = 1; //Store y
//Thread.MemoryBarrier();
r1 = x; //Load x
}
static void Thread2()
{
x = 1; //Store x
//Thread.MemoryBarrier();
r2 = y; //Load y
}
static void Main(string[] args)
{
//총 9번의 테스트 진행
for(int i = 1; i <= 9; ++i)
{
int count = 0;
while (true)
{
++count;
x = y = r1 = r2 = 0;
Task task1 = new Task(Thread1);
Task task2 = new Task(Thread2);
task1.Start();
task2.Start();
//task1, task2가 끝날때까지 기다린다.
Task.WaitAll(task1, task2);
//이 코드는 이론적으로 task1, task2가 끝나야 실행된다
//r1, r2가 둘다 0이 될 수 없는 조건
if (r1 == 0 && r2 == 0) { break; }
}
Console.WriteLine($"{i}번째 케이스의 시도횟수는 {count}번");
}
}
}
}
- 각 스레드에서 값을 저장하고, 읽어오는 과정에서 break 조건문이 무조건 거짓이 나오도록 하지만, 놀랍게도 이 테스트케이스는 break가 참이 되며, 빠져나오는 것을 볼 수 있습니다.
- 각 케이스마다 실행되는 횟수가 모두 다른것을 볼 수 있습니다.
Thread.MemoryBarrier(); //메모리 배리어 사용
- 메모리 배리어를 사용하면 컴파일러 최적화처럼 CPU파이프라인 및 캐시에 의한 코드 재배치로 인해 스레드 내의 연산 순서가 바뀔 수 있는 경우를 억제합니다.
📑 메모리 배리어
namespace ServerCore
{
class Program
{
static int x = 0;
static int y = 0;
static int r1 = 0;
static int r2 = 0;
static void Thread1()
{
y = 1; //Store y
Thread.MemoryBarrier();
r1 = x; //Load x
}
static void Thread2()
{
x = 1; //Store x
Thread.MemoryBarrier();
r2 = y; //Load y
}
static void Main(string[] args)
{
//총 9번의 테스트 진행
for(int i = 1; i <= 9; ++i)
{
int count = 0;
while (true)
{
++count;
x = y = r1 = r2 = 0;
Task task1 = new Task(Thread1);
Task task2 = new Task(Thread2);
task1.Start();
task2.Start();
//task1, task2가 끝날때까지 기다린다.
Task.WaitAll(task1, task2);
//이 코드는 이론적으로 task1, task2가 끝나야 실행된다
//r1, r2가 둘다 0이 될 수 없는 조건
if (r1 == 0 && r2 == 0) { break; }
}
Console.WriteLine($"{i}번째 케이스의 시도횟수는 {count}번");
}
}
}
}
- 메모리 배리어를 사용하여 연산 순서가 변경되는 코드재배치를 방지하고, 가시성을 보장하여 코드 상에서 보인 break조건문에 대해 항상 거짓이 나오도록 되었습니다.
- 실행 결과(count 출력) 또한 나오지 않은것을 확인할 수 있습니다.
'server > socket server' 카테고리의 다른 글
[C# 서버] Context Switching (0) | 2023.01.04 |
---|---|
[C# 서버] 스핀락 (0) | 2023.01.04 |
[C# 서버] 원자성, Interlocked, Monitor, lock (0) | 2023.01.02 |
[C# 서버] volatile (0) | 2022.12.30 |
[C# 서버] 멀티스레드(Multi-thread) 기초 (0) | 2022.12.30 |