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

wocl00님의 프로필 이미지
wocl00

작성한 질문수

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

SpinLock

number가 0이 안되는 상황이 이해가 않습니다.

작성

·

294

0

public void Acquire()

        {

            while (_locked)  // 화장실 문이 비어있을 때 까지 대기를 한다. 

            {       }

            // 들어가서 문을 잠그는 작업 

            _locked = true;

        }

이렇게 화장실에 들어가는 과정과 잠그는 과정이 달라서, 그 시간차 동안에 두 쓰레드가 동시에 공유 자원에 접근해서 number에 0이지 나오지 않는다고 설명해주셨습니다. 

 

근데 이 설명이 잘 이해가 가지 않습니다. 

 

위 코드에 화장실에 2명이 들어간다는 게 어떤 의미인가요? 

 

제가 이해한 바로는 _locked이 false가 되어 while문을 빠져나왔을 때 다른 쓰레드도 Acquire함수에 접근하여, 두 쓰레드에서 _locked에 true를 대입하는 것으로 이해했습니다. 

 

근데 이러한 이유 때문에 number++와 number-- 연산에서 에러가 나는 과정이 이해가 되지 않습니다. 결국 for문을 만번이든, 10만번이든 돈 다는 뜻은 number++ 혹은 nunber-- 연산을 했다는 뜻인데 

 

왜 number에 0이 출력되지 않고 이상한 값이 출력되는지 잘 모르겠습니다. 

 

number++ 혹은 number-- 연산이 스킵이 되는 과정이 이해가 안갑니다. 

 

 

 

답변 1

4

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

위 코드에 화장실에 2명이 들어간다는 게 어떤 의미인가요? 

말 그대로입니다. 문이 열려 있다고 급히 들어가다 보니 2명이 들어간 것이죠.
코드에선 원래 while() 부분을 통과하는 것은 딱 1개의 쓰레드여야 하는데,
코드에 문제가 있어 다수의 쓰레드를 통과시킨 것이죠.

제가 이해한 바로는 _locked이 false가 되어 while문을 빠져나왔을 때 다른 쓰레드도 Acquire함수에 접근하여, 두 쓰레드에서 _locked에 true를 대입하는 것으로 이해했습니다. 

while (_locked)  // 화장실 문이 비어있을 때 까지 대기를 한다.
{       }
// 들어가서 문을 잠그는 작업 
_locked = true;

네 맞습니다. 위에서 while () 부분을 거의 동시에 실행해서 둘 다 빠져나오고,
_locked = true를 동시에 실행하는 것이죠.

근데 이러한 이유 때문에 number++와 number-- 연산에서 에러가 나는 과정이 이해가 되지 않습니다. 결국 for문을 만번이든, 10만번이든 돈 다는 뜻은 number++ 혹은 nunber-- 연산을 했다는 뜻인데 왜 number에 0이 출력되지 않고 이상한 값이 출력되는지 잘 모르겠습니다.  number++ 혹은 number-- 연산이 스킵이 되는 과정이 이해가 안갑니다. 

number++와 number--에 '에러'가 나는 것은 아니고
연산이 스킵이 되는 것도 아닙니다.
양쪽 다 10만번 호출은 했지만 그냥 결과가 0이 아닌 것 뿐이죠.
이 부분은 atomic을 다룰 때 설명을 했으니 다시 복습을 해보시기 바랍니다.

우리 눈에는 number++이 하나의 연산으로 보이지만
내부적으로 CPU 명령어 단으로 보면 저 명령어는
1) number라는 메모리 주소에 있는 값을 갖고오고
2) 그 값에다 1을 더하고
3) 다시 number의 메모리 주소에 결과값을 저장하는
단계로 이루어져 있습니다.
이를 동시에 여러 쓰레드에서 실행하면,
쓰레드 A에서 1-2 단계까지 호출하고 3을 아직 안 한 상태에서
쓰레드 B가 끼어들면, 아직 A의 3이 적용되기 전이라 증가되기 전의 값으로 연산을 하게 됩니다.

 

wocl00님의 프로필 이미지
wocl00

작성한 질문수

질문하기