Page 36 -
P. 36

우선 여러 스레드가 동시에 num을 읽습니다. 그리고 num을 증가시킵니다. num을 증가시키는 연산
               은 기계어로 컴파일하면 다음과 같이 여러 줄이 나옵니다.             *


                코드 num 연산의 기계어 코드
                 r1 = num
                 r1 = r1 + 1
                 num = r1


               여러 줄이기 때문에 컨텍스트 스위치를 할 때 어디서 실행하다 멈추어야 할지 모를 수밖에 없습니

               다. 이 때문에 같은 값을 두 번 연산한다든지 아니면 값을 건너뛰고 연산한다든지 같은 여러 가지
               문제가 발생합니다.

               그런데 뭔가 이상합니다. 우리가 경험한 것은 앞서 본 것처럼 이상한 값이 들어간 정도의 문제
               가 아니라, 충돌(crash)이 난 상황입니다. 건드려서는 안 되는 메모리 공간을 건드린 것입니다.
               Array<int> primes에서요. 왜 충돌이 발생했을까요?

               num이라는 정보를 보관하는 데 필요한 것은 정수형 4바이트 데이터 공간 하나뿐입니다. 하지만
               Array<int> primes 정보를 보관하는 데 필요한 데이터는 하나 이상입니다. 우선 Array<int>는 배
               열 객체를 가리키는 포인터 변수와 배열이 크기를 멤버 변수로 가질 것입니다. 배열 객체는 메모

               리 힙에서 할당되었을 것이고, 메모리 힙은 현재 실행 중인 프로세스의 런타임 라이브러리로 다루
               어집니다.

                  그림 1-23 Array<int>의 데이터 구조

               primes             3   5   7
               ptr
               size = 3
                             무효              무효


               각 스레드는 소수를 찾아내면 Array<int> 객체에 Add() 함수를 사용하여 배열 맨 뒤를 채웁니다.
               기존에 가진 배열 객체에 더 이상 넣을 공간이 없으면, 메모리를 재할당합니다. C 언어의 런타임
               같은 경우 메모리를 재할당한 후 메모리를 가리키는 주소가 달라지는 경우가 종종 있습니다. 그리

               고 메모리 재할당 여부와 관계없이 배열 크기를 의미하는 변수 값도 1 증가할 것입니다.







               *     실제로는 MOV, INC 같은 기계어(명령어)로 만들어집니다. 여기서는 여러분 이해를 돕고자 C 언어 형식으로 표현했습니다.

         044
   31   32   33   34   35   36   37