프로세스 병렬 처리 시 동기화가 필요한 이유

이찬영·2021년 8월 16일
0

OS

목록 보기
8/35

프로세스 병렬 처리 시 문제점

프로세스를 병렬 처리시 스케쥴링을 통하여 프로세스의 일부분만 실행 된 후 다음 프로세스의 일부를 실행하게 된다는것을 알고있다.

여기서 문제점은 한 프로세스에서 자원에 대한 사용이 끝나지 않은 상태에서 스케쥴링이 이루어져고 다른 프로세스가 같은 자원을 사용하게 되면 우리는 원하지 않는 결과값을 얻을 수 있을것이다.

produce-consume 패턴을 통해 위의 문제점을 살펴보겠다.

produce-consume 패턴을 통한 문제 발생 예

아래는 produce 코드이다

while(1){
	while(count == BUFFER_SIZE);
    
    buffer[in] = next_produced;
    in = (in +1) % BUFFER_SIZE;
    count++;
}

아래는 consume 코드이다

while(1){
	while(count == 0);
    
    next_consumed = buffer[out];
    out = (out +1) % BUFFER_SIZE;
    count--;
}

count 값이 현재 5라고 생각하자.

발생하는 경우

  1. produce의 프로세스가 완전히 실행되면 결과적으로 count의 값은 6이 된다. 이후 consume 프로세스가 완전히 실행되면 count 값은 5가 된다.

  2. produce의 프로세스가 count++ 코드가 완료되지 않은 후 consume 프로세스로 스케쥴링 된다. consume 프로세스 또한 count-- 코드가 완료되지 않은 후 produce 프로세스로 스케쥴링 된다.
    produce 프로세스가 완전히 실행된다면 produce 프로세스의 count = 6이 된다.
    이후 consume 프로세스로 스케쥴링되서 남은 코드가 실행 되면 cousume의 count = 4가 된다.

발생하는 이유

2번의 경우가 가능한 이유는 context switching이 발생하면 register에 존재하는 값을 저장하게 된다. 이후에 다시 프로세스가 CPU에 할당 받게 되면 context에 존재하는 정보들을 가져오게 된다. 이때 register에 존재 했던 count의 값실제 메모리에 상주하는 count의 값은 달라 질 수 있다.

count 값이 레지스터에 저장되는게 이해가 안될 수 있다.
이해를 돕기 위해 count를 조작하는 증감 연산자의 기계어를 보면 아래와 같다.

register = count
register = register + 1
count = register

레지스터에 count변수 값을 할당하고 증감 연산을 한후 (+1이나 -1) 레지스터에 값을 count 변수에 할당한다. 만약 register = count까지 실행된 후 다른 프로세스로 스케쥴링이 되고 다시 할당이 된다면 register = register + 1부터 실행하게 된다. 이때 register에 저장한 값과 count의 값이 같다고 보장할 수 없다는것을 알 수 있다. 이유로는 위에 설명한것처럼 context switching시 register의 값들을 저장 후 불러왔기 때문이다.

결론

이러한 문제처럼 실행 되는 특정 순서에 결과가 의존하는 상황을 race condition(경쟁 상황)이라고 한다. 레이스 컨디션으로 보호하기 위해, 하나의 프로세스만이 특정 변수를 조작하도록 보장해야한다. 이러한 보장을 위해 우리는 프로세스들이 동기화 되도록 할 필요가 있다.

0개의 댓글