동기화 (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)
: 공유가 불가능한 자원의 동시 사용을 피하기 위해 사용하는 알고리즘
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 (임계 구역)
: 공유 데이터의 일관성을 보장하기 위해 하나의 프로세스/스레드만 진입해서 실행 가능한 영역
① mutual exclusion (상호 배제)
: 어떤 프로세스가 critical section(CS)에 진입해서 작업을 수행 중이면 다른 모든 프로세스들은 CS에 진입할 수 없다.
② progress (진행)
: CS에 진입한 프로세스가 없고 CS에 진입하려는 프로세스가 있으면, CS 진입을 허용한다.
③ bounded waiting (유한 대기)
: CS에 들어가기 위해서 무한대기 하는 프로세스가 존재하면 안 된다. (starvation 현상)
④ 동일 속도
: 프로세스들의 상대적인 속도에 대해서는 어떠한 가정도 하지 않는다.
race condition (경쟁 상태)
: 여러 프로세스/스레드가 동시에 같은 데이터를 조작할 때 타이밍이나 접근 순서에 따라 결과가 달라질 수 있는 상황
① 공유 메모리를 사용하는 프로세스 사이에서 발생
② 커널 모드 수행 중 interrupt가 발생하여 인터럽트 처리루틴이 수행되는 경우
③ 프로세스가 시스템콜을 하여 커널 모드로 수행중인데 context switch가 일어나는 경우
④ Multi-processor에서 shared memory 내의 kernel data에 동시 접근하는 경우