[운영체제] 동기화 (synchronization)

cosmos-JJ·2023년 10월 4일
0

Computer Science

목록 보기
12/15
post-thumbnail

동기화 (synchronization)

동기화 (synchronization) :여러 프로세스/스레드가 동시에 실행해도 공유 데이터의 일관성을 유지하는 것 (== 프로세스/스레드 사이의 수행 시기를 맞추는 것)

프로세스/스레드 사이의 수행 시기를 맞춘다는 것은?

  • 실행 순서 제어 : 프로세스/스레드를 올바른 순서대로 실행하기
  • 상호 배제 : 동시에 접근해서는 안되는 자원에 하나의 프로세스만 접근하게 하기

실행 순서 제어를 위한 동기화

Example

프로세스1 : writer ➡ Book.txt 파일에 값을 저장하는 프로세스
프로세스2 : reader ➡ Book.txt 파일에 저장된 값을 읽는 프로세스

① 프로세스1


# 값을 파일에 저장하는 코드
def writer(filename, data):
   
   with open(filename, 'w') as file:
   		file.write(data)

book_data = "example"
writer("book.txt", book_data)

② 프로세스2

# 파일에서 값을 읽어오는 코드
def reader(filename):

with open(filename, 'r') as file:
	data = file.read()
	return data

read_data = reader("book.txt")

위 예제를 보면 두 프로세스는 동시에 실행할 수 있을까?

정답은 X 이다.

프로세스2(reader)는 프로세스1(writer) 실행이 끝나야 실행할 수 있기 때문이다.
즉 프로세스2는 'book.txt안에 값이 존재한다'는 특정 조건이 만족되어야 실행을 이어나갈 수 있다.

이렇게 동시에 실행 되는 프로세스를 올바른 순서로 실행하는 것이 실행 순서 제어를 위한 동기화이다.


상호 배제를 위한 동기화

상호 배제 (mutual exclusion) : 공유가 불가능한 자원의 동시 사용을 피하기 위해 사용하는 알고리즘

  • 즉, 특정 한 시점에 단 하나의 프로세스만이 Criticla Section에 접근할 수 있는 것
  • ex) 공유 자원을 사용하는 A,B스레드가 있을 때 A스레드가 공유 자원을 사용하는 중에 B가 데이터를 변경해버리면 다시 A스레드가 데이터를 읽을 때 올바르게 결과값이 나오지 않을 수 있다.

Producer & Consumer Problem

Producer & Consumer Problem (생산자와 소비자 문제)

import threading

# 공유 변수
sum = 0


def produce():
    global sum
    for i in range(100000):
            sum += 1

def consume():
    global sum
    for i in range(100000):
            sum -= 1


print("초기 합계:", sum)
    
# 스레드 생성
producer = threading.Thread(target=produce)
consumer = threading.Thread(target=consume)

# 스레드 시작
producer.start()
consumer.start()

# 스레드가 종료할 때까지 대기
producer.join()
consumer.join()


print("producer, consumer 스레드 실행 이후 합계:", sum)

https://github.com/kangtegong/self-learning-cs/blob/main/producer_consumer/producer_consumer.cpp 사이트를 참고하여 python 으로 구현한 코드


위 코드는 언뜻 보기에 아무 문제가 없어 보인다.
생산자는 sum이란 공유 변수에 1을 증가시키고, 소비자는 sum이란 공유 변수에 1을 감소시킨다.
그래서 보통은 총합 변수가 계속 0일 것이라고 기대한다.

하지만 이 코드에서는 produce와 consume 함수가 락 또는 다른 동기화 메커니즘 없이 sum을 동시에 수정하므로, 실행 결과가 예측할 수 없다.
race condition이 발생할 사능성이 있으며, 최종 합계가 0이 아닐 수도 있다.

즉 Producer & Consumer Problem는 동시에 접근해서는 안 되는 자원에 동시에 접근했기에 발생한 문제이다


critical section (임계 구역)

critical section (임계 구역) : 공유 데이터의 일관성을 보장하기 위해 하나의 프로세스/스레드만 진입해서 실행 가능한 영역


critical section problem의 해결책이 되기 위한 조건

① mutual exclusion (상호 배제)
: 어떤 프로세스가 critical section(CS)에 진입해서 작업을 수행 중이면 다른 모든 프로세스들은 CS에 진입할 수 없다.

② progress (진행)
: CS에 진입한 프로세스가 없고 CS에 진입하려는 프로세스가 있으면, CS 진입을 허용한다.

③ bounded waiting (유한 대기)
: CS에 들어가기 위해서 무한대기 하는 프로세스가 존재하면 안 된다. (starvation 현상)

④ 동일 속도
: 프로세스들의 상대적인 속도에 대해서는 어떠한 가정도 하지 않는다.


race condition (경쟁 상태)

race condition (경쟁 상태) : 여러 프로세스/스레드가 동시에 같은 데이터를 조작할 때 타이밍이나 접근 순서에 따라 결과가 달라질 수 있는 상황

  • 공유 데이터의 최종 연산 결과는 마지막에 공유 데이터를 다룬 프로세스가 누구인지에 따라 달라진다.
  • race condition을 막기 위해서는 공유 데이터에 대한 동시 접근을 동기화 해야한다.

race condition이 발생하는 예

① 공유 메모리를 사용하는 프로세스 사이에서 발생

② 커널 모드 수행 중 interrupt가 발생하여 인터럽트 처리루틴이 수행되는 경우

  • 인터럽트 처리 루틴(Interrupt Service Routine, ISR) ➡ 커널 코드
  • 커널 모드 수행 중 interrupt가 발생하면 커널 영역의 공유 데이터에 동시(중복) 접근이 일어나는 race condition 상황이 발생한다.

③ 프로세스가 시스템콜을 하여 커널 모드로 수행중인데 context switch가 일어나는 경우

  • A 프로세스가 시스템 콜을 하여 커널 모드로 수행 중인 상황이다. (커널 영역의 공유 데이터를 처리하고 있다고 가정)
  • 그런데 A 프로세스 작업 중간에 B 프로세스가 CPU를 선점하고, B 프로세스가 시스템 콜을 통해 커널 영역의 공유 데이터에 접근하면 race condition 상황이다.

④ Multi-processor에서 shared memory 내의 kernel data에 동시 접근하는 경우

  • 해결방법은 한번에 하나의 CPU만 커널에 들어갈 수 있게 하거나
  • 커널 내부에 있는 각 공유 데이터에 접근할 때마다 그 데이터에 대한 lock / unlock을 수행한다.

참고

profile
🤍도전하는 건 즐거워요🤍

0개의 댓글