MultiThread 동작 시 하나의 변수에 대해 2개의 Thread가 값을 변경할 경우 예상과 다른 결과가 나올 수 있다.
 - 값 연산 횟수가 많아질수록 더 심해진다.

 

이유
 - Assembly Level에서의 변수의 값증가 행위는 3단계로 나뉜다.
  1. 해당 변수의 주소에 접근하여 값을 ecx register에 임시 저장한다.
  2. ecx를 1증가 시킨다.
  3. ecx값을 변수 주소에 다시 넣어준다.
- Multi Thread에 경우 Atomic(원자성)이 보존되지 않아 1번 동작이 2개의 Thread에서 동시에 일어나게 되면 서로 다른 연산을 하게된다.
 - 이 경우 "변수의 주소"는 Critical Section(임계 영역)이라고 한다.

// c#에서 증가
number++;

// Assembly에서 증가
mov exc, dword ptr[주소] // number주소에서 exc로 number값 저장
inc exc // exc(number에서 가져온값)을 1증가
mov dword ptr[주소], exc // exc의 증가된값을 number 주소로 다시 넣어준다.

// Assembly를 C#느낌으로 쉽게 풀어쓰면
int temp = number;
temp++;
number = temp;

 Interlocked
- Atomic을 보장하는 기능
- 2개의 Thread가 하나의 주소에 접근할 경우 둘 중 먼저 접근한 Thread의 연산처리가 끝난뒤 다른 Thread가 순차적으로 접근하여 연산하게 된다.
- 때문에 성능상의 저하는 피할 수 없다.

MultiThread환경에서 변수의 증감에 대한 Atomic한 결과를 확인하는 방법

// 잘못된 방법
Interlocked.Increment(ref number);
int result = number; // 이 시점에 number가 위에서 증가된 이후에 실행됐다는 보장이 없다.

// 옳바른 방법
// Interlocked.Increment의 반환값은 증가된 순간의 값을 반환하므로 Atomic한 값이다.
int result = Interlocked.Increment(ref number);

'프로그래밍 > 네트워크' 카테고리의 다른 글

SpinLock  (0) 2021.09.01
Lock  (0) 2021.08.29
Cache  (0) 2021.08.27
Thread의 생성  (0) 2021.08.27
Thread란?  (0) 2021.08.26

+ Recent posts