✔️동기화
프로세스 동기화: 프로세스들 사이의 수행 시기를 맞추는 것
- 실행 순서 제어: 프로세스를 올바른 순서대로 실행하기
- 상호 배제: 동시에 접근해서는 안되는 자원에 하나의 프로세스만 접근하게 하기
공유 자원: 공동으로 사용하는 자원 (변수,파일,장치 등)
임계 구역: 공유 자원에 접근하는 코드 중 동시에 실행하면 문제가 발생하는 코드 영역
레이스 컨디션: 잘못된 실행으로 인해 여러 프로세스가 동시 다발적으로 임계 구역의 코드를 실행하여 문제가 발생하는 경우
운영체제는 임계 구역 문제를 해결하고자 3가지 원칙을 지킨다.
- 상호 배제: 한 프로세스가 임계 구역에 진입시 다른 프로세스는 임계 구역에 들어올 수 없다.
- 진행: 임계 구역에 어떤 프로세스도 진입하지 않았다면 임계 구역에 진입하고자 하는 프로세스는 들어갈 수 있어야 한다.
- 유한 대기: 한 프로세스가 임계 구역에 들어오기 위해 무한정 대기해서는 안 된다.
✔️동기화 기법
뮤텍스 락: 임계 구역을 잠금으로써 프로세스 간의 상호 배제를 이루는 동기화 도구
뮤텍스 락의 구현
- 프로세스들이 공유하는 전역 변수 lock
- 임계 구역을 잠그는 acquire 함수
- 임계 구역의 잠금을 해제하는 release 함수
뮤텍스 락은 지속적으로 공유 자원을 사용할 수 있는지 프로세스가 확인해야 하기 때문에 CPU주기를 낭비할 수 있다.
세마포: 공유 자원이 여러 개 있는 상황에서 적용이 가능한 동기화 도구
세마포의 구현
- 임계 구역에 진입할 수 있는 프로세스의 개수인 전역 변수 S
- 임계 구역의 진입 여부를 알려주는 wait 함수
- 임계 구역 앞에서 기다리는 프로세스에게 신호를 주는 signal 함수
세마포는 wait 함수 호출시 사용 가능 자원이 없을 경우 해당 프로세스 상태를 대기 상태로 변경, 세마포를 위한 대기 큐에 집어 넣는다. signal 함수가 호출되어 자원을 사용할 수 있게 될 시 대기 중이었던 프로세스를 대기 큐에서 제거, 프로세스 상태를 준비 상태로 변경 후 준비 큐로 옮겨주는 방법을 활용함으로써 뮤텐스 락의 문제점을 해결할 수 있다.
모니터: 공유 자원과 공유 자원에 접근하기 위한 인터페이스(통로)를 묶어 관리하는 프로세스 동기화 도구, 조건 변수 활용
이때, 프로세스는 반드시 인터페이스를 통해서만 공유 자원에 접근할 수 있다.
조건 변수: 프로세스나 스레드의 실행 순서를 제어하기 위해 사용하는 변수
지피티를 활용한 예제
import threading
import time
# 뮤텍스 락 예제
class MutexExample:
def __init__(self):
self.lock = threading.Lock()
self.counter = 0
def increment(self):
with self.lock: # 뮤텍스 락 획득
local_counter = self.counter
local_counter += 1
time.sleep(0.1)
self.counter = local_counter
def run(self):
threads = [threading.Thread(target=self.increment) for _ in range(10)]
for t in threads:
t.start()
for t in threads:
t.join()
print(f"Final counter (Mutex): {self.counter}")
# 세마포 예제
class SemaphoreExample:
def __init__(self):
self.semaphore = threading.Semaphore(3) # 동시에 3개 스레드만 접근 가능
def access_resource(self, thread_id):
with self.semaphore:
print(f"Thread {thread_id} is accessing the resource")
time.sleep(1)
print(f"Thread {thread_id} is releasing the resource")
def run(self):
threads = [threading.Thread(target=self.access_resource, args=(i,)) for i in range(10)]
for t in threads:
t.start()
for t in threads:
t.join()
# 모니터 예제
class MonitorExample:
def __init__(self):
self.condition = threading.Condition()
self.data = []
def producer(self):
with self.condition:
for i in range(5):
self.data.append(i)
print(f"Produced: {i}")
time.sleep(0.5)
self.condition.notify() # 소비자에게 알림
def consumer(self):
with self.condition:
self.condition.wait() # 생산자가 알릴 때까지 대기
while self.data:
item = self.data.pop(0)
print(f"Consumed: {item}")
def run(self):
t1 = threading.Thread(target=self.producer)
t2 = threading.Thread(target=self.consumer)
t1.start()
t2.start()
t1.join()
t2.join()
if __name__ == '__main__':
print("Mutex Lock Example")
MutexExample().run()
print("\nSemaphore Example")
SemaphoreExample().run()
print("\nMonitor Example")
MonitorExample().run()
✔️교착 상태
교착 상태: 일어나지 않을 사건을 기다리며 진행이 멈춰 버리는 현상
교착 상태 발생 조건
- 상호 배제
- 점유와 대기: 자원을 할당받은 상태에서 다른 자원을 할당받기 기다리는 상태
- 비선점
- 원형 대기: 프로세스들이 원의 형태로 자원을 대기하는 것
교착 상태 해결 방법
- 교착 상태 예방: 교착 상태 발생 조건을 제거함으로써 예방
- 교착 상태 회피: 교착 상태가 발생하지 않을 정도로만 자원을 할당하는 방식으로 안전 상태를 유지한다.
- 안전 상태: 모든 프로세스가 정상적으로 자원을 할당받고 종료될 수 있는 상태, 안전 순서열이 존재
- 불안전 상태: 교착 상태가 발생할 수도 있는 상황, 안전 순서열이 존재하지 않는다.
- 안전 순서열: 교착 상태 없이 안전하게 프로세스들에 자원을 할당할 수 있는 순서
- 교착 상태 검출 후 회복: 교착 상태 발생을 인정하고 사후 조치하는 방식
- 선점을 통한 회복: 교착 상태가 해결될 때까지 한 프로세스씩 자원을 몰아주는 방식
- 프로세스 강제 종료를 통한 회복 : 모두 강제 종료하거나 교착 상태가 없어질 때까지 한 프로세스씩 강제 종료
- 타조 알고리즘: 교착 상태 무시
숙제
'공부' 카테고리의 다른 글
RFM 분석 공부(Feat. 챗지피티) (0) | 2025.05.09 |
---|---|
[혼공컴운] 6주차_ 가상메모리/파일 시스템 (0) | 2025.02.22 |
[혼공컴운]4주차_운영체제/프로세스와 스레드/CPU 스케줄링 (0) | 2025.02.09 |
[혼공컴운]3주차_메모리와 캐시 메모리/보조기억장치/입출력장치 (0) | 2025.01.26 |
[혼공컴운]2주차_CPU의 작동 원리/CPU 성능 향상 기법 (0) | 2025.01.19 |