class Program
{
static int x = 0;
static int y = 0;
static int r1 = 0;
static int r2 = 0;
static void Main(string[] args)
{
int count = 0;
while(true)
{
count++;
x = y = r1 = r2 = 0;
Task t1 = new Task(Thread1);
Task t2 = new Task(Thread2);
t1.Start();
t2.Start();
Task.WaitAll(t1, t2);
if (r1 == 0 && r2 == 0)
break;
}
Console.WriteLine($"{count}번만에 루프 탈출");
}
static void Thread1()
{
y = 1;
Thread.MemoryBarrier();
// Full Memory Barrier
// 현재 스레드를 실행 중인 프로세서는 MemoryBarrier()에 대한 호출 이전의 메모리 액세스가 MemoryBarrier()에 대한 호출 이후의 메모리 액세스 뒤에 실행되는 방식으로 명령을 다시 정렬할 수 없습니다.
r1 = x;
}
static void Thread2()
{
x = 1;
Thread.MemoryBarrier();
r2 = y;
}
}
https://learn.microsoft.com/ko-kr/dotnet/api/system.threading.thread.memorybarrier?view=net-7.0
스레드 내에 Thread.MemoryBarrier 구문이 없는 경우,
y = 1;
r1 = x;
위 두 구문이 종속성이 없다고 판단한 컴파일러가 두 구문의 순서를 바꿀 수 있다. ( 두 스레드 모두 동일 )
Thread.MemoryBarrier 를 명시하여 메모리 액세스 순서를 보장한다.
디스어셈블리로는 확인이 불가능했다.
뒤집힘을 확인할 수 있는 방법이 있을까?
'C#' 카테고리의 다른 글
[C#] Dispose 패턴 (0) | 2023.03.23 |
---|---|
[C#] Interlocked (0) | 2023.03.20 |
[C#] 캐시 Special Locality 테스트 (0) | 2023.03.05 |
[C#] 컴파일러 최적화로 인한 데드락 예제 (0) | 2023.03.03 |
[C#] Thread Join 예제 (0) | 2023.02.27 |