인프런 커뮤니티 질문&답변

시슴님의 프로필 이미지
시슴

작성한 질문수

[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버

SpinLock 강의 중 이해가 안되는 부분이 있어 질문드립니다.

해결된 질문

작성

·

166

0

안녕하세요

SpinLock 강의를 듣다 이해가 안되는점이 있어 질문드립니다

SpinLock 강의 4분 30초쯤에

Thread_1 함수와 Thread_2 함수를 정의했고

Thread_1 함수는

for(int i=0;i<i<100000;i++)

{

_lock.Acquire();

_num++;

_lock.relaese():

}

Thread_2 함수는

for(int i=0;i<i<100000;i++)

{

_lock.Acquire();

_num--;

_lock.relaese():

}

이렇게 되어있는데 여기서 이해가 안되는 점이

race condition에 의해 실행 순서가 예측이 불가능할 뿐이지

결국 Thread_1 함수의 for문 num++이 10만번 실행되고

Thread_2 함수의 for문 num--이 10만번 실행되는건 똑같으니까

10만 - 10만 = 0 이 나와야 된다 생각했지만

실제로는 0이 안되고 강의에서는 -8914로 나오는지 이해가 안됩니다.

 

답변 2

1

시슴님의 프로필 이미지
시슴
질문자

아.. 이해됐습니다

num++을 하고 나서 그 값을 가져온 뒤 num--을 하거나

num--을 하고 나서 그 값을 가져온 뒤 num++을 하는줄 알았는데

원자성이 보장되지 않아 num++ 과 num--를 둘다 해버리는 상황이 오고

num++값과 num--값을 둘 중 한 개의 값만 저장해야 하기 때문에

0이아닌 +1 또는 -1 값이 저장되고 꼬여버리는 상황이 온지 알겠습니다

race condition이 추상적으로만 이해됐는데

이제 이해가 된거같네요 답변 감사드립니다 

1

Rookiss님의 프로필 이미지
Rookiss
지식공유자

lock을 걸지 않을 때 왜 0이 아닌 다른 값이 나오는지 질문하신 것 같은데,
해당 부분이 완전히 이해가 안 가신다면 Interlocked 강의를 복습해보시기 바랍니다.
_num++이나 _num--가 우리 눈에는 1줄짜리 코드로 보이지만, 실제로는:

int temp = num;
temp = temp + 1;
num = temp;

와 비슷하게
- (1) 메모리에서 레지스터로 값을 갖고 오고;
- (2) 값 1증가 (혹은 감소)
- (3) 레지스터 값을 다시 메모리에 값 저장

하는 일련의 과정으로 이루어져 있습니다.
왜냐하면 특정 메모리 값을 1 증가시키는 것을 CPU가 한 번에 처리할 수 없기 때문이죠.

lock을 걸지 않거나 Interlocked 계열 (atomic이 보장된) 함수를 사용하지 않는다면
여러 쓰레드가 동시에 접근하게 되면서
동시에 위의 1~2 단계를 통과할 수가 있게 됩니다. (3은 실행되지 않은 상태)

가령 num이 0인 상태에서,
두 쓰레드가 동시에 num++, num--을 한 번씩 실행한다 치면
num의 값을 갖고올 때 
int temp = num;

이 부분에서 둘 다 동일하게 0을 갖고 올 가능성이 생깁니다.
그러면 한쪽은 1, 한 쪽은 -1을 결과값으로 주장해서 
그것을 최종 결과물에다 저장하겠지만, num = temp;
우리가 예상한 바와 같이 1과 -1이 모두 더해진 0이라는 결과물이 아닌
+1이나 -1 중 하나로 결과 값이 남게 됩니다.

시슴님의 프로필 이미지
시슴

작성한 질문수

질문하기