동시 프로그래밍에서 여러 프로세스나 스레드가 공유 자원에 접근하게 되면 예상치 못한 동작이나 에러가 발생할 수 있다. 이런 문제를 방지하기 위해서 프로그램에서 공유 자원에 접근하는 "로직"을 보호하는데, 이렇게 보호된 코드의 영역을 **임계 구역**이라고 한다. (내가 헷갈렸어서 다시 강조하자면...) 임계 구역은 **코드의 일부**이다! 임계 구역 코드에는 공유 자원(전역 변수나 파일, 데이터베이스 등...)에 접근하는 명령들이 들어 있다. 여러 스레드나 프로세스가 이 코드를 실행하면 데이터가 꼬이거나 잘못된 결과가 나올 수 있기 때문에, 임계 구역은 "**한번에 하나만 실행되도록 보호**"되어 있다. ```c // 공유 변수 int counter = 0; void increment() { // 👇 여기가 임계 구역 counter = counter + 1; } ``` - 코드 블록 : **임계 구역** - 보호 대상 : **공유 자원** 임계 구역은 코드 블록의 일부이지만, 임계 구역 자체를 보호한다는게 아니라 공유 자원을 보호하기 위해서 공유 자원을 다루는 부분을 임계 구역으로 만든다는 연관 관계를 헷갈리지 말자! ## 임계 구역 문제(Critical Section Problem) ### 임계 구역 문제 임계 구역 문제는 여러 프로세스가 동시에 공유 자원에 접근하려고 하는 상황에서, 이 접근을 적절하게 제어하지 않는다면 데이터 불일치나 경쟁 상태(race condition)가 발생할 수 있다는 문제가 있다. 이 문제를 해결하기 위해서 OS나 프로그래머가 공유 자원에 동시에 접근하지 못하게 하면서도 프로그램 전체가 멈추지 않도록 하는 방법이 있어야 한다...! 즉 **여러 프로세스나 스레드가 동시에 실행될 때 이 임계 구역에 어떻게 들어갈지를 조율**하는 방법을 찾아야 한다는 문제이다. ### 임계 구역 문제를 해결하기 위한 조건 임계 구역 문제를 해결하기 위한 방법들이 갖춰야 할 조건이 3가지 있다. 1. **상호 배제 (Mutual Exclusion)** 임계 구역에는 한번에 하나의 프로세스/스레드만 들어갈 수 있다. 공유 자원에 여러 실행 단위가 동시에 접근하면 값이 꼬이기 때문에 이 조건을 지켜야 함. 2. **진행 (Progress)** 임계 구역에 아무도 없을 때, 누가 접근할 지 결정하는 것은 무한정 지연되지 않고 진행되어야 한다. 3. **한정된 대기 (Bounded Waiting)** 어떤 프로세스/스레드가 임계 구역 진입을 요청했으면 이 프로세스/스레드는 언젠가는 들어가야 한다. 무한정 기다리는 기아(Starvation)가 발생하면 안 된다. > [!note] > - **진행** -> 임계 구역이 비었을 때는 누군가가 빨리 들어가야 한다. 즉 자원이 놀면 안된다. > - **한정된 대기** -> 임계 구역 진입을 요청한 프로세스/스레드는 무한히 기다려서는 안 된다. 즉, 굶주리면 안된다.