고전적인 동기화 문제 3가지
Bounded Buffer
생산자 소비자 문제를 다시 생각해보자. 생산자는 full 버퍼를 만드는 데, 소비자는 empty 버퍼를 만드는 데 각자의 목표가 있다. 여기서 공유 데이터에 접근하기 위해서는 mutex를 통해 버퍼에 하나의 프로세스만 접근하도록 해야한다. 아래 코드에서 볼 수 있다시피 각각의 프로세스는 wait으로 버퍼가 다 비워지거나 채워질 때까지 기다리고 mutex로 한 번에 한 프로세스만 접근할 수 있도록 한다. 그리고 프로세스가 다 끝나면 signal을 통해 프로세스가 다 실행되었다는 것을 알린다.
Readers Writers
프로세스가 동시에 실행되고 있는 상태를 자세히 들여다보니, 읽기만 계속 실행되는 것과 쓰기만 계속 실행되는 것처럼 편향적으로 실행되는 프로세스가 존재한다는 것이 관찰할 수 있었다. DB를 예로 들면 SELECE문을 통해 read만 하는 작업이나 UPDATE를 통해 write만 하더라는 것이다.
그런데 이를 생각해보면 read가 동시에 동작하는 것은 그저 데이터를 읽는 것이기 때문에 동기화 문제를 고려하지 않아도 된다. 하지만 문제는 write이다. write 작업만 있거나 read와 write가 같이 있는 작업처럼 write가 있다면 그때부터는 동기화 문제를 생각해야 한다.
이런 혼돈을 막기 위해 두 가지의 변형을 할 수가 있다. 첫번째는 read에게 우선권을 주는 것이다. 하지만 이렇게 하면 write가 기회를 얻지 못하고 기아 상태가 될 수 있다. 두번째는 write에게 우선권을 주는 것이다. 이렇게 하면 반대로 read가 기아 상태가 될 수도 있고 write가 너무 많으면 다른 write 또한 기아 상태가 될 수 있다. 하지만 write가 더 중요할 때가 많기 때문에 두번째 변형을 사용하는 경우가 많다.
Dining Philosophers
식사하는 철학자는 동기화에서 오래된 문제이다. 5명의 철학자들과 5개의 젓가락이 있다고 하자. 그리고 철학자들은 식사를 하기 위해서는 두 개의 젓가락이 필요하다. 만약 철학자들이 동시에 배가 고파져서 젓가락을 동시에 잡으려고 한다면 어떤 문제가 발생할까? 아마 하나의 젓가락을 공유하게 되면서 경쟁 상태가 생기게 된다.
상호배제 문제를 해결하기 위한 가장 간단한 방법은 각 젓가락에 세마포어를 주는 것이다. 하지만 이렇게 하면 큰 문제가 발생하는데 바로 데드락 문제가 생기게 되는 것이다. 동시에 배가 고파져서 각자의 왼쪽에 있는 젓가락을 집고 오른쪽에 있는 젓가락을 집으려고 한다면 여기서 데드락 문제가 발생하는 것이다.
데드락 문제를 해결하는 방법은 무엇이 있을까? 여러 방법들이 있겠지만 asymmetric한 방법을 살펴보도록 하자. 이 방법은 홀수 철학자들은 무조건 왼쪽을 먼저 집고 오른쪽을 집게하고, 짝수 철학자들은 그 반대로 하게 한다면 이러한 데드락 문제를 해결할 수 있을 것이다. 하지만 이러한 방법도 기아 문제까지 완벽하게 해결하지는 못한다.
다른 대안
thread-safe한 동시성 앱을 만들기 위해서는 다른 대안을 생각해 볼 수 있다. 대표적으로 3가지 정도가 있다.
1. 트랜잭션 메모리
원자성을 가진 실행단위를 트랜잭션이라고 한다. 메모리 자체를 트랜잭션하게 만들어서 동기화 문제를 제어한다.
2. OpenMP
앞에서 살펴본 것처럼 지정한 코드 영역을 임계구역으로 만들어주는 라이브러리이다.
3. 함수형 프로그래밍 언어
명령형 프로그램은 폰 노이만 아키텍쳐에 따라 명령어를 실행하기 때문에 동기화 문제가 발생할 수 있다. 함수형 프로그래밍은 모든 단위가 함수이기 때문에 이러한 문제에서 벗어날 수 있다. 대표적으로 scala가 있다.
'CS 지식 > 운영체제' 카테고리의 다른 글
운영체제 Ch9 - 메인 메모리 (0) | 2022.01.05 |
---|---|
운영체제 Ch8 - 데드락 (0) | 2022.01.03 |
운영체제 Ch6 - 프로세스 동기화(2) (0) | 2021.12.12 |
운영체제 Ch6 - 프로세서 동기화(1) (0) | 2021.12.12 |
운영체제 Ch5 - CPU 스케줄링 (0) | 2021.12.08 |