해결된 질문
작성
·
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
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 중 하나로 결과 값이 남게 됩니다.