11. 프로세스 동기화: Chapter 6. Synchronization Tools (Part 1)

HotFried·2023년 9월 12일

Cooperating processes

  • 한 프로세스가 다른 프로세스에게 영향을 받거나 주는 프로세스

  • logical address space를 공유하거나, data를 공유(share memory or message-passing)

  • shared data에 cuncurrent하게 접근할 때  data inconsistency 를 고려해야 한다.

  • concurrent하게 실행되는 프로세스들이 정해진 순서로 실행(orderly execution)되도록 보장해주어야 데이터의 consistency 가 유지된다.

The “integrity of data” shared by several processes(or threads)

  • Concurrent execution : 실행 중인 프로세스가 interrupt를 받고, 다른 프로그램이 실행된다. → Shared data가 존재한다면 데이터 동기화에 문제가 발생함
  • Parallel execution : 여러 개의 프로세스가 여러 개의 CPU에서 실행되면 마찬가지로 동기화 문제가 발생함

생산자-소비자 문제 상황으로 살펴보기

  • 두 프로세스는 data를 공유하고 비동기적(asynchronously)으로 실행된다.

  • buffer에 item이 몇 개 존재하는지 체크하기 위해서 정수 형 변수 count를 추가한다.

    • 0으로 초기화
    • 새로운 item이 추가될 때 → 증가
    • item이 제거될 때 → 감소

<생산자 코드> - producer.c

while (true)
{
    while (count == BUFFER_SIZE)
        ; // 아무것도 실행하지 않음.
    buffer[in] = next_produced;
    in = (in + 1) % BUFFER_SIZE;
    count++; // count 1 증가
}

<소비자 코드> - consumer.c

while (true)
{
    while (count == 0)
        ; // 아무것도 실행하지 않음.
    next_consumed = buffer[out];
    out = (out + 1) % BUFFER_SIZE;
    count--; // count 1 감소
}

두 프로세스가 개별적으로 잘 작동해도 Data inconsistency 발생한다.

→ 간단한 예제를 통해 확인해보자

#include <stdio.h>
#include <pthread.h>

int sum = 0;

void* run(void* param)
{
	for (int i = 0; i < 10000; ++i)
	{
		sum++;
	}
	pthread_exit(0);
}

int main()
{
	pthread_t tid1, tid2;
	pthread_create(&tid1, NULL, run, NULL);
	pthread_create(&tid2, NULL, run, NULL);
	pthread_join(tid1, NULL);
	pthread_join(tid2, NULL);
	printf("%d\n", sum);
}
  • 실행 결과 : 논리대로 20000이 나올 때도 있지만 그렇지 않을 때도 존재한다.

왜 이런 문제가 발생할까?

count++, count—가 기계어로 어떻게 구현되는지 살펴보자

→ 명령어 실행 중에 Context switch가 발생한다면? 값이 달라진다.

∴ 어디에서 Context switch가 발생하는 지에 따라 결과가 달라질 수 있다.

Race Condition (경쟁 상황)

  • 여러 개의 프로세스(or 스레드)가 Shared dataconcurrent하게 접근할 때, 실행 순서에 따라 그 결과가 달라져서 데이터 일관성(Data Consistency)을 해칠 수 있는 상태 → synchronization : 특정 시간에 오직 하나의 프로세스만 공유 데이터에 접근하게 하도록, 프로세스를 동기화

Critical Section Problem (임계영역)

  • Shared Data” 접근 순서에 따라 실행 결과가 달라지는 프로그램의 영역

    → 어떤 프로세스가 critical section을 실행하고 있을 때는 다른 프로세스들이 접근하지 못하게 한다. (동시에 실행하지 못하게 한다.)

  • Sections of codes

    • entry-section : Critical Section 진입 허가 요청
    • critical-section : Critical Section
    • exit-section : Critical Section 퇴출
    • remainder-section : 나머지 코드 영역
  • Critical Section Problem 해결을 위한 3가지 조건

    • Mutual Exclusion(상호배제)
      한 프로세스가 critical section을 실행 중일 때 다른 프로세스는 critical section을 실행할 수 없다.

    • Progress flexibility (avoid deadlock)
      어떤 프로세스도 Critical section을 실행하고 있지 않은데, 프로세스들이 Critical section에 진입하고 싶은 경우 진입이 무한대로 연기되는 상황(deadlock)이 발생하면 안된다. → 한 프로세스가 다른 프로세스의 진행을 방해해서는 안된다.

    • Bounded Waiting (avoid starvation)
      Critical section으로 진입하기 위해 대기하는 모든 쓰레드는 일정 시간 이내에 Critical section으로 진입할 수 있어야 한다.
  • Critical Section Problem 해결 방법

    • single-core 환경 해결 방법 Shared Data에 접근 중일 때 Interrupt 방지 → multiprocessor에서 적절하지 않은 방법 (모든 코어의 interrupt 방지하게 되면 성능 저하)

    • 두 가지 일반적인 방법
      • preemptive kernels 프로세스가 언제든지 선점 당할 수 있기 때문에 동기화 문제가 반드시 발생한다. 응답성이 뛰어나다.
      • non-preemptive kernels CPU를 할당 받은 프로세스 종료 → 새로운 프로세스에 CPU 할당 → context switch가 발생하지 않고, 경쟁 상황이 발생하지 않는다. 성능이 좋지 않기 때문에 잘 사용하지 않는다.

참고 :

Silberschatz et al. 『Operating System Concepts』. WILEY, 2020.

주니온TV@Youtube: 자세히 보면 유익한 코딩 채널

profile
꾸준하게

0개의 댓글