์ธ๋งํฌ์ด
๐ ๋ฝ๊ณผ ์กฐ๊ฑด๋ณ์๋ณด๋ค ๊ฐ๋ ฅํ ๋๊ธฐํ ๋๊ตฌ? ๋ฐ๋ก ์ธ๋งํฌ์ด!
๋ฉํฐ์ฐ๋ ๋ ํ๋ก๊ทธ๋๋ฐ์ ํ๋ค ๋ณด๋ฉด ์ด๋ฐ ์ํฉ์ ์์ฃผ ๋ง๋๊ฒ ๋ฉ๋๋ค.
- ์ฌ๋ฌ ๊ฐ์ ์ฐ๋ ๋๊ฐ ํ๋์ ์์์ ๋์์ ์ฌ์ฉํ๋ ค ํ๋ค
- ์ด๋ค ์ฐ๋ ๋๋ ํน์ ์กฐ๊ฑด์ด ๋ง์กฑ๋ ๋๊น์ง ๊ธฐ๋ค๋ ค์ผ ํ๋ค
- ๋๊ฐ ๋จผ์ ์คํ๋์๋๋์ ๋ฐ๋ผ ํ๋ก๊ทธ๋จ์ด ๊ผฌ์ผ ์ ์๋ค
์ด๋ด ๋ ์ฐ๋ฆฌ๊ฐ ํํ ์ฌ์ฉํ๋ ๋๊ตฌ๊ฐ ๋ฝ(mutex)๊ณผ ์กฐ๊ฑด ๋ณ์(condition variable)์
๋๋ค.
ํ์ง๋ง… ์ธ๋งํฌ์ด(semaphore) ํ๋๋ฉด ์ด ๋์ ์ญํ ์ ์ ๋ถ ํ ์ ์๋ค๋ ์ฌ์ค, ์๊ณ ๊ณ์
จ๋์?
โ ์ธ๋งํฌ์ด๋?
์ธ๋งํฌ์ด๋ '์ซ์ ํ๋๋ฅผ ์กฐ์ํ๋ฉด์ ์ฐ๋ ๋ ๊ฐ ๋๊ธฐํ๋ฅผ ํ๋ ๊ธฐ๋ฒ'์
๋๋ค.
๋ง ๊ทธ๋๋ก ์ ์ ํ๋๋ฅผ ๊ฐ๊ณ wait/post ์ฐ์ฐ๋ง์ผ๋ก ์ฌ๋ฌ ์ฐ๋ ๋๋ฅผ ์กฐ์จํ๋ ๊ฑฐ์ฃ !
#include <semaphore.h>
sem_t s;
sem_init(&s, 0, 1); // ์ธ๋งํฌ์ด ์ด๊ธฐ๊ฐ 1
sem_wait(&s); // ์์ ํ๋ ์๋ (์ ๊ทธ๊ธฐ)
sem_post(&s); // ์์ ๋ฐํ (ํ๊ธฐ)
sem_wait(&s)
- ์ธ๋งํฌ์ด s์ ๊ฐ์ 1 ๊ฐ์
- ์ค์ธ ๊ฒฐ๊ณผ๊ฐ 0 ์ด์์ด๋ฉด, ๊ณ์ ์งํํฉ๋๋ค.
- ์์๋ฉด, ํ์ฌ ์ฐ๋ ๋๋ ๊ธฐ๋ค๋ฆผ(wait/block) ์ํ๋ก ๋ค์ด๊ฐ๋๋ค.
sem_post(&s)
- ์ธ๋งํฌ์ด s์ ๊ฐ์ 1 ์ฆ๊ฐ
- ์ด๋ ๋๊ธฐ ์ค์ธ ์ฐ๋ ๋๊ฐ ์๋ค๋ฉด, ๊ทธ ์ค ํ๋๋ฅผ ๊นจ์๋๋ค.
์ด๊ฑธ ์ด์ฉํ๋ฉด ๋ฝ์ฒ๋ผ๋, ์กฐ๊ฑด๋ณ์์ฒ๋ผ๋ ์ฌ์ฉํ ์ ์์ด์.
๐ค ๊ทธ๋ผ ์ธ๋งํฌ์ด ๊ฐ์ด ์ ์์๊ฐ ๋ ์ ์์ฃ ?
์ธ๋งํฌ์ด์ ๊ฐ์ ๋๊ธฐ ์ค์ธ ์ฐ๋ ๋ ์๋ฅผ ๋ํ๋ผ ์๋ ์๊ธฐ ๋๋ฌธ์
๋๋ค.
์๋ฅผ ๋ค์ด:
- ์ด๊ธฐ๊ฐ์ด 1์ธ ์ด์ง ์ธ๋งํฌ์ด (๋ฝ ์ญํ )
- ์ฐ๋ ๋ A๊ฐ sem_wait() → -1 → ๊ฐ์ 0
- ์ฐ๋ ๋ B๊ฐ sem_wait() → -1 → ๊ฐ์ -1 → ์ฐ๋ ๋ B: ๋๊ธฐ ์ํ
์ฆ, ์ธ๋งํฌ์ด์ ๊ฐ์ด 0๋ณด๋ค ์์ผ๋ฉด ๊ทธ๋งํผ์ ์ฐ๋ ๋๊ฐ ๋๊ธฐ ์ค์ด๋ผ๋ ์๋ฏธ์ ๋๋ค.
๐ ์ด์ง ์ธ๋งํฌ์ด = ๋ฝ
์ธ๋งํฌ์ด๋ฅผ 1๋ก ์ด๊ธฐํํ๊ณ ํ ๋ฒ์ ํ๋์ ์ฐ๋ ๋๋ง ์ ๊ทผํ๊ฒ ํ๋ฉด ๋ฝ์ฒ๋ผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
sem_t mutex;
sem_init(&mutex, 0, 1);
sem_wait(&mutex); // ๋ฝ ํ๋
// ์๊ณ ๊ตฌ์ญ
sem_post(&mutex); // ๋ฝ ํด์
์ฐ๋ ๋ 0: sem_wait()๋ฅผ ํธ์ถํ๋ค -> ์ธ๋งํฌ์ด ๊ฐ์ 1 ๊ฐ์์์ผ 0์ผ๋ก ๋ง๋ ๋ค
์ฐ๋ ๋ 0: ๋ฝ์ ๋ณด์ ํ๊ณ ์์ ๋
<์ํฉ>
์ฐ๋ ๋0์ด sem_wait()๋ฅผ ํธ์ถ ํ์ฌ ์๊ณ ์์ญ์ ์ง์ ํ์ง๋ง ์์ง sem_post()๋ฅผ ํธ์ถํ์ง ์์ ๊ฒฝ์ฐ
์ฐ๋ ๋ 1๊ฐ sem_wait()๋ฅผ ํธ์ถํ์ฌ ์๊ณ ์์ญ ์ง์ ์ ์๋ํ๋ ๊ฒฝ์ฐ
์ฐ๋ ๋ 1: ์ธ๋งํฌ์ด ๊ฐ์ -1๋ก ๊ฐ์์ํค๊ณ ์ฐ๋ ๋1์ ๋๊ธฐ์ ๋ค์ด๊ฐ๋ค.
๐ด ์กฐ๊ฑด ๊ธฐ๋ค๋ฆด ๋๋ ์ธ๋งํฌ์ด!
์ธ๋งํฌ์ด ์ด๊ธฐ๊ฐ์ 0์ผ๋ก ํ๋ฉด, ๊ธฐ๋ณธ์ ์ผ๋ก ๋๊ธฐ ์ํ์
๋๋ค.
์๋ฅผ ๋ค์ด, ๋ถ๋ชจ ์ฐ๋ ๋๊ฐ ์์ ์ฐ๋ ๋์ ์ข
๋ฃ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ์ฝ๋๋ ์ด๋ ๊ฒ ๋ง๋ค ์ ์์ด์
์์์ ๋๊ธฐ ์ค์ธ ๋ถ๋ชจ : ์ด๊ธฐ๊ฐ์ 0์ผ๋ก ํ๋ค
sem_t done;
sem_init(&done, 0, 0); // 0์ผ๋ก ์ด๊ธฐํ
void* child(void*) {
printf("child\n");
sem_post(&done); // ์์์ ๋์์ด ๋๋๋ฉด ->๋ถ๋ชจ๋ฅผ ๊นจ์ด๋ค!
return NULL;
}
int main() {
printf("parent: begin\n");
pthread_create(..., child, ...);// ์์ ์ฐ๋ ๋ ์์ฑ
sem_wait(&done); // ์์ ๋๋ ๋๊น์ง ๋๊ธฐ
printf("parent: end\n");
}
์ํฉ1) ์์ ํ๋ก์ธ์ค ์์ฑ ํ, ์์ง ์์ ํ๋ก์ธ์ค๊ฐ ์คํ์ ์์ํ์ง ์์ ๊ฒฝ์ฐ
์์์ด sem_post()๋ฅผ ํธ์ถํ๊ธฐ ์ ์
๋ถ๋ชจ๊ฐ sem_wait()๋ฅผ ํธ์ถํ ๊ฒ์ด๋ค.
๋ถ๋ชจ ํ๋ก์ธ์ค๋ ์์์ด ์คํ๋ ๋๊น์ง ๋๊ธฐํด์ผ ํ๋ค.
๋ถ๋ชจ๊ฐ ์คํ๋๋ฉด ์ธ๋งํฌ์ด ๊ฐ์ ๊ฐ์์ํค๊ณ ๋๊ธฐํ๋ค.
์์์ด ์คํ๋แจฉ์ ๋ sem_post()๋ฅผ ํธ์ถํ์ฌ ์ธ๋งํฌ์ด์ ๊ฐ์ 0์ผ๋ก ์ฆ๊ฐ์ํจ ํ ๋ถ๋ชจ๋ฅผ ๊นจ์ด๋ค
๋ถ๋ชจ๋ sem_wait()์์ ๋ฆฌํด์ ํ์ฌ ํ๋ก๊ทธ๋จ์ ์ข ๋ฃ.
์ํฉ2) ๋ถ๋ชจ ํ๋ก์ธ์ค๊ฐ sem_wait()๋ฅผ ํธ์ถํ๊ธฐ ์ ์, ์์ ํ๋ก์ธ์ค์ ์คํ์ด ์ข ๋ฃ๋ ๊ฒฝ์ฐ
์์์ด ๋จผ์ sem_post()๋ฅผ ํธ์ถํ์ฌ ์ธ๋งํฌ์ด์ ๊ฐ์ 0์์ 1๋ก ์ฆ๊ฐ์ํจ๋ค.
๋ถ๋ชจ๊ฐ ์คํํ ์ ์๋ ์ํฉ์ด ๋๋ฉด sem_wait() ๋ฅผ ํธ์ถํ๋ค.
์ธ๋งํฌ์ด ๊ฐ์ด 1์ธ ๊ฒ์ ๋ฐ๊ฒฌํ ๊ฒ์ด๋ค.
๋ถ๋ชจ๋ ์ธ๋งํฌ์ด ๊ฐ์ 0์ผ๋ก ๊ฐ์์ํค๊ณ sem_wait()์์ ๋๊ธฐ ์์ด ๋ฆฌํดํ๋ค
๐ ์์ฐ์ / ์๋น์ ๋ฌธ์ ? ์ธ๋งํฌ์ด๋ก ์๋ฒฝ ํด๊ฒฐ!
์ ๋ช ํ ์์ฐ์-์๋น์ ๋ฌธ์ ๋ ์ธ๋งํฌ์ด๋ก ๋ฉ์ง๊ฒ ํด๊ฒฐ๋ฉ๋๋ค. ํต์ฌ์ ๋ ๊ฐ์ง ์ธ๋งํฌ์ด:
- empty → ๋น ๋ฒํผ ๊ณต๊ฐ ๊ฐ์ (์ด๊ธฐ๊ฐ: ๋ฒํผ ํฌ๊ธฐ)
- full → ์ฑ์์ง ๋ฐ์ดํฐ ์ (์ด๊ธฐ๊ฐ: 0)
์์ฐ์๋ empty๋ฅผ ๊ธฐ๋ค๋ฆฌ๊ณ full์ ์ฌ๋ฆผ
์๋น์๋ full์ ๊ธฐ๋ค๋ฆฌ๊ณ empty๋ฅผ ์ฌ๋ฆผ
์ฌ๊ธฐ์ mutex ์ธ๋งํฌ์ด๋ฅผ ๋ํด ์๊ณ ๊ตฌ์ญ ๋ณดํธ๋ ์๋ฒฝ!
MAX=1 ์ผ ๋
MAX=10 ์ผ ๋
์์ฐ์์ ์๋น์ ์ฐ๋ ๋๋ค์ด ์ฌ๋ฌ ๊ฐ ์๋ค๊ณ ํ์.
๋ ์ฐ๋ ๋๊ฐ put() ์ ๊ฑฐ์ ๋์์ ํธ์ถํ๋ฉด ๊ฒฝ์ ์กฐ๊ฑด์ด ๋ฐ์ํ๋ค
์ฐ๋ ๋1: ๋จผ์ ์คํ๋์ด์ ๋ฒํผ์ ์ฒซ ๊ณต๊ฐ์ ๊ฐ์ ๋ฃ๊ธฐ ์์ํ๋ค
์ฐ๋ ๋1: fill ์นด์ดํฐ ๋ณ์๊ฐ 1๋ก ๋ณ๊ฒฝํ๊ธฐ ์ ์ ์ธํฐ๋ฝํธ๊ฐ ๊ฑธ๋ ธ๋ค
์ฐ๋ ๋2: ๋ฒํผ์ ์ฒซ ๋ฒ์งธ ๊ณต๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ -> ์ฐ๋ ๋1์ด ๊ธฐ๋กํ ์ด์ ์ ๊ฐ์ ์๋ก์ด ๊ฐ์ผ๋ก ๋์ฒด
๊ฒฝ์ ์กฐ๊ฑด ํด๊ฒฐ : ์ํธ ๋ฐฐ์ ์ถ๊ฐ
๐ ์ mutex๊ฐ ํ์ํ ๊น?
๋ฒํผ์ ๊ฐ์ ๋ฃ๊ฑฐ๋ ๊บผ๋ด๋ put()๊ณผ get()์ ๊ณต์ ์์(๋ฒํผ)์ ์์ ํฉ๋๋ค.
→ ๋์์ ์ฌ๋ฌ ์ฐ๋ ๋๊ฐ ๋ค์ด์ค๋ฉด ๋ฐ์ดํฐ๊ฐ ๊ผฌ์ผ ์ ์์ด์!
๊ทธ๋์ mutex ์ธ๋งํฌ์ด๋ฅผ ๋ฝ์ฒ๋ผ ์ฌ์ฉํด์,
ํ ๋ฒ์ ํ ๋ช
๋ง ๋ฒํผ๋ฅผ ๊ฑด๋๋ฆฌ๊ฒ ๋ง๋๋ ๊ฑฐ์์.
์ด๋ฆ | ์ค๋ช | ์ด๊ธฐ๊ฐ |
empty | ๋ฒํผ์ ๋น์ด ์๋ ์นธ ์ | MAX (๋ฒํผ ํฌ๊ธฐ) |
full | ๋ฒํผ์ ์ฑ์์ง ์นธ ์ | 0 |
mutex | ๐ ๊ณต์ ์์ ์ ๊ทผ์ 1๋ช ๋ง ํ์ฉํ๋ ๋ฝ | 1 (์ด์ง ์ธ๋งํฌ์ด) |
โ ์์ฐ์ ์ฝ๋ ์์ฝ
sem_wait(&empty); // ๋ฒํผ ๋น ์นธ ํ๋ ์ค์ด๊ธฐ (์์ผ๋ฉด ๋๊ธฐ)
sem_wait(&mutex); // ๋ฝ ์ก๊ธฐ (๋ค๋ฅธ ์ ๋ค ๋ชป ๋ค์ด์ค๊ฒ)
put(i); // ๋ฒํผ์ ๋ฐ์ดํฐ ๋ฃ๊ธฐ
sem_post(&mutex); // ๋ฝ ํ๊ธฐ
sem_post(&full); // ์ฑ์ด ์นธ ์ ์ฆ๊ฐ (์๋น์ ๊นจ์ฐ๊ธฐ)
โ ์๋น์ ์ฝ๋ ์์ฝ
sem_wait(&full); // ์ฑ์์ง ์นธ์ด ์์ผ๋ฉด ๊ธฐ๋ค๋ฆผ
sem_wait(&mutex); // ๋ฝ ์ก๊ธฐ (๋ฒํผ ๊ฑด๋๋ฆด ์ค๋น)
int tmp = get(); // ๋ฒํผ์์ ๋ฐ์ดํฐ ๊บผ๋
sem_post(&mutex); // ๋ฝ ํ๊ธฐ
sem_post(&empty); // ๋น ์นธ ์ ์ฆ๊ฐ (์์ฐ์ ๊นจ์)
โ ํต์ฌ ์์ฝ
- empty, full: ์์ฐ์/์๋น์ ๊ฐ ํ์ด๋ฐ ์กฐ์
- mutex: ๋ฒํผ ์์ฒด๋ฅผ ๋ณดํธํ๋ ๋ฝ
์ด ์ธ ๊ฐ์ง ์ธ๋งํฌ์ด๋ง ์ ์กฐํฉํ๋ฉด, ์์ ํ ๋์ ํ๋ก๊ทธ๋๋ฐ์ด ๊ฐ๋ฅํฉ๋๋ค!
๐ ์ธ๋งํฌ์ด vs ๋ฝ+์กฐ๊ฑด๋ณ์?
๊ตฌ๋ถ | ์ธ๋งํฌ์ด | ๋ฝ + ์กฐ๊ฑด ๋ณ์ |
๋๊ธฐํ ๋ฐฉ์ | ์ ์ ๊ธฐ๋ฐ, wait/post | ๋ฝ + ์กฐ๊ฑด ๋๊ธฐ / ์๊ทธ๋ |
๊ตฌํ ๋์ด๋ | ๋จ์ํ์ง๋ง ์ง๊ด์ ์ด์ง ์์ ์ ์์ | ๋ ๋ช ํํ ๊ตฌ์กฐํ ๊ฐ๋ฅ |
์ ์ฐ์ฑ | ๋ฝ๋ ๋๊ณ , ์กฐ๊ฑด ๋ณ์๋ ๋จ | ์ญํ ๋ถ๋ฆฌ |
๋ํ ์ฌ์ฉ ์์ | Reader-Writer ๋ฝ, ์ฒ ํ์ ๋ฌธ์ | ํน์ ์กฐ๊ฑด ๋๊ธฐ ์ํฉ |
๐ Reader-Writer ๋ฝ์ด๋?
โ ์ ํ์ํ ๊น?
- ์ด๋ค ๋ฐ์ดํฐ๋ ์ฝ์ ๋๋ ์ถฉ๋์ด ์ ๋์ง๋ง,
- ์ธ ๋๋ ์ถฉ๋์ด ๋์!
์์: ๋์๊ด ์ฑ
- ์ฌ๋ฌ ๋ช ์ด ๋์์ ์ฑ ์ ์ฝ๋ ๊ฑด OK โ
- ๋๊ตฐ๊ฐ ์ฑ ์ ๋์(์ฐ๊ธฐ)๋ฅผ ํ๋ค๋ฉด? → ํผ์๋ง ํด์ผ ํจ โ
๐งฉ ํต์ฌ ์์ด๋์ด
- Reader(์ฝ๊ธฐ): ์ฌ๋ฌ ์ฐ๋ ๋๊ฐ ๋์์ ์ฝ์ด๋ ๋จ
- Writer(์ฐ๊ธฐ): ํผ์๋ง ์จ์ผ ํจ. ์ฝ๊ธฐ๋ ๋ชป ๋ค์ด์ค๊ฒ ํด์ผ ํจ
๐ง ๊ตฌ์กฐ์ฒด ์ค๋ช
typedef struct _rwlock_t {
sem_t lock; // readers ์นด์ดํธ๋ฅผ ๋ณดํธํ๋ ๋ฝ
sem_t writelock; // ์ค์ ์ฐ๊ธฐ ๋ณดํธ ๋ฝ
int readers; // ํ์ฌ ์ฝ๊ณ ์๋ reader ์
} rwlock_t;
- readers: ํ์ฌ ์ฝ๊ณ ์๋ ์ฐ๋ ๋ ์
- lock: readers ๊ฐ์ ์กฐ์ํ ๋ ์ถฉ๋ ์ ๋๊ฒ ๋ณดํธ
- writelock: ์ฐ๊ธฐ ์ฐ๋ ๋๊ฐ ๋ค์ด๊ฐ ๋ ์ฌ์ฉํ๋ ์ง์ง ๋ฝ
โ ์ฝ๊ธฐ ๋ฝ ํ๋ (rwlock_acquire_readlock)
sem_wait(&rw->lock); // readers ์ ๋ณดํธ์ฉ ๋ฝ
rw->readers++;
if (rw->readers == 1)
sem_wait(&rw->writelock); // ์ฒซ ๋ฒ์งธ ๋ฆฌ๋๋ง writelock ์ ๊ธ
sem_post(&rw->lock); // readers ์ ์กฐ์ ๋โ
- ์ฝ๋ ์ฌ๋์ด ์ฒ์ ํ ๋ช ์ผ ๋๋ง writelock์ ์ก์์.
- ๊ทธ ์ดํ ๋ฆฌ๋๋ค์ ๊ทธ๋ฅ count๋ง ๋๋ฆฌ๊ณ ๋ค์ด๊ฐ์.
- ์ฌ๋ฌ ๋ฆฌ๋๊ฐ ๋์์ ์ฝ์ ์ ์์ด์!
โ ์ฝ๊ธฐ ๋ฝ ํด์ (rwlock_release_readlock)
sem_wait(&rw->lock);
rw->readers--;
if (rw->readers == 0)
sem_post(&rw->writelock); // ๋ง์ง๋ง ๋ฆฌ๋๊ฐ ๋๊ฐ ๋ writelock ํด์
sem_post(&rw->lock);
- ๋ง์ง๋ง ์ฝ๋ ์ฌ๋์ด ๋๊ฐ๋ฉด writelock์ ํ์ด์ค๋๋ค.
- ์ด์ writer๊ฐ ๋ค์ด๊ฐ ์ ์๊ฒ ๋ฉ๋๋ค.
โ ์ฐ๊ธฐ ๋ฝ ํ๋ & ํด์
sem_wait(&rw->writelock); // ์ฐ๋ ค๋ฉด ๋ฌด์กฐ๊ฑด ๋จ๋
์ง์
!
...
sem_post(&rw->writelock);
- ์ฐ๋ ์ฐ๋ ๋๋ writelock์ ํผ์ ์ก๊ณ ์์
- ์ฝ๋ ์ฌ๋ ํ๋๋ผ๋ ์์ผ๋ฉด ๋ชป ๋ค์ด๊ฐ!
๐ง ๋ง๋ฌด๋ฆฌ: ์ธ๋งํฌ์ด๋ ๋๊ธฐํ์ ๋ง๋ฅ๋๊ตฌ!
์ธ๋งํฌ์ด๋ ๋ฝ๋ ๋๊ณ , ์กฐ๊ฑด ๋ณ์๋ ๋๊ณ , ์ฌ์ง์ด ๋์ ํฉ์น ๊ฒ ์ด์์ ๊ฐ๋ ฅํ๊ณ ์ ์ฐํ ๋๊ตฌ์
๋๋ค.
๋จ, ๋๋ฌด ์์ ๋กญ๊ธฐ ๋๋ฌธ์ ์๋ชป ์ฐ๋ฉด ๊ต์ฐฉ ์ํ(deadlock)๋ ๊ธฐ์(starvation)์ ๋น ์ง ์ ์์ผ๋ ์ฃผ์!
๋ฉํฐ์ฐ๋ ๋ ํ๊ฒฝ์ ์ค๊ณํ ๋, ์ธ๋งํฌ์ด๋ผ๋ ๋๊ตฌ๋ฅผ ์ ํ์ฉํด ๋ณด์ธ์.
์ ํํ๊ฒ๋ง ์ฐ๋ฉด, ๋ณต์กํ ๋๊ธฐํ ๋ฌธ์ ๋ ๊น๋ํ๊ฒ ํด๊ฒฐํ ์ ์์ต๋๋ค! ๐ช
๐ฝ๏ธ ์์ฌํ๋ ์ฒ ํ์ ๋ฌธ์ ๋?
๋ค์ฏ ๋ช ์ ์ฒ ํ์๊ฐ ๋ฅ๊ทผ ์ํ์ ์์ ์๊ณ , ์ฒ ํ์๋ ์๊ฐํ๊ฑฐ๋ ๋จน์ ์ ์์ด์.
์์ฌ๋ฅผ ํ๋ ค๋ฉด ์ผ์ชฝ๊ณผ ์ค๋ฅธ์ชฝ์ ํฌํฌ 2๊ฐ๋ฅผ ๋ชจ๋ ์ง์ด์ผ ํด์.
ํฌํฌ๋ ์ฒ ํ์ ์ฌ์ด์ ํ๋์ฉ ์์ด์ ์ด 5๊ฐ์์.
while (1) {
think(); // ์๊ฐ ์ค
getforks(); // ์์ชฝ ํฌํฌ ์ก๊ธฐ (์ผ์ชฝ, ์ค๋ฅธ์ชฝ)
eat(); // ์์ฌ
putforks(); // ํฌํฌ ๋ด๋ ค๋๊ธฐ
}
์ด ๊ฐ๋จํ ์ค์ ์์ ๋ค์๊ณผ ๊ฐ์ ๋ณํ ํ๋ก๊ทธ๋๋ฐ์ ํต์ฌ ๋ฌธ์ ๋ค์ด ๋ฑ์ฅํฉ๋๋ค:
1. ๐ ๊ต์ฐฉ ์ํ (Deadlock)
๋ชจ๋ ์ฒ ํ์๊ฐ ๋์์ ์ผ์ชฝ ํฌํฌ๋ฅผ ์ง๊ณ ,
์ค๋ฅธ์ชฝ ํฌํฌ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ฉด?
→ ์์ํ ๊ธฐ๋ค๋ฆฌ๊ฒ ๋จ. ํ๋ก๊ทธ๋จ ๋ฉ์ถค.
2. ๐ซ ๊ธฐ์ ์ํ (Starvation)
์ฒ ํ์ A๋ ๊ณ์ ํฌํฌ๋ฅผ ์ก์ง ๋ชปํ๊ณ ๊ตถ์ฃผ๋ฆผ.
→ ์ด๋ค ์ฐ๋ ๋๋ ์์ํ ์์ ๋ชป ๋ฐ๋ ์ํฉ.
3. โ๏ธ ๋ณํ์ฑ (Concurrency)
- ๊ฐ๋ฅํ ๋ง์ ์ฒ ํ์๊ฐ ๋์์ ๋ฐฅ ๋จน์ ์ ์์ด์ผ ํจ์จ์ .
- ๋จ, ์์ ํ๊ฒ!
โ ์ ๋ฆฌ: ์ ์ด ๋ฌธ์ ๊ฐ ๋์๋๊ฐ?
์ด์ | ์ค๋ช |
๋๊ธฐํ์ 3๋ ์ด์ ์ค๋ช ๊ฐ๋ฅ | ๊ต์ฐฉ, ๊ธฐ์, ๋ณํ์ฑ |
๋น์ ๊ฐ ์ง๊ด์ ์ | ์ฒ ํ์ = ์ฐ๋ ๋, ํฌํฌ = ๊ณต์ ์์ |
๋ฉด์ ๊ณผ ์ํ ๋จ๊ณจ | ๊น์ด ์๊ณ , ์งง์ ์ฝ๋๋ก ๊ตฌํ ๊ฐ๋ฅ |
์ธ๋งํฌ์ด, ๋ฎคํ ์ค ์์ฉ ๋ฌธ์ ๋ก ์ ํฉ | ์ค์ ๋๊ธฐํ ๊ธฐ์ ์ ๋ฃ์ด์ ํ๊ฒ ๋ง๋ฆ |
1๏ธโฃ Lock๊ณผ Conditon Variable ๋์ ์ ์ธ๋งํฌ์ด๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ฌด์์ธ๊ฐ?
- ์ธ๋งํฌ์ด == Lock: ์ธ๋งํฌ์ด์ ๊ฐ์ด 1์ด๋ฉด ๋ฎคํ ์ค(Lock)์ฒ๋ผ ๋์ (์ด์ง ์ธ๋งํฌ์ด).
- ์ธ๋งํฌ์ด == Condtion Variable: ์กฐ๊ฑด์ ๊ธฐ๋ค๋ฆฌ๋ ๋์ , ์ธ๋งํฌ์ด์ ๊ฐ์ด 0์ด๋ฉด wait(), ๊ฐ์ด ์ฆ๊ฐํ๋ฉด signal()์ฒ๋ผ wake-up ํจ๊ณผ ๋ฐ์.
- ์ธ๋งํฌ์ด๋ wait()/signal() ํธ์ถ ์ ์ด๋ค ์ฐ๋ ๋๊ฐ ๊นจ์ด๋ ์ง ์ ์ดํ๊ธฐ ์ด๋ ค์
- ์กฐ๊ฑด ๋ณ์๋ ๋ฝ๊ณผ ์ ํํ๊ฒ ๊ฒฐํฉ๋์ด ์๊ณ ์กฐ๊ฑด ๋ถ๋ณ์(predicate)์ ์ฒดํฌ ํ wait ํ๋ ํจํด์ ๊ฐ์ ํ ์ ์์ง๋ง ์ธ๋งํฌ์ด๋ ๊ทธ๋ฐ ๊ตฌ์กฐ๊ฐ ์ฝํฉ๋๋ค.
- ๊ทธ๋์ ๊ฐ๋ฅํ์ง๋ง ๋ ๋ณต์กํด์ง๊ณ ์ ์ง๋ณด์๊ฐ ์ด๋ ค์ → ์ผ๋ฐ์ ์ผ๋ก ๋ฝ + ์กฐ๊ฑด ๋ณ์๋ฅผ ๊ทธ๋๋ก ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ๋์ ์ค๊ณ์ ๋๋ค.
2๏ธโฃ ์ธ๋งํฌ์ด์ ์ ์๋ ๋ฌด์์ธ๊ฐ?
์ธ๋งํฌ์ด (Semaphore):
- ์ ์๊ฐ์ ๊ฐ์ง๋ ๋๊ธฐํ ์์(primitive).
- ์์์ ์ฐ์ฐ ์ ๊ณต:
- wait() ๋๋ P() ๋๋ down() → ๊ฐ ๊ฐ์. 0๋ณด๋ค ์์์ง๋ฉด ๋ธ๋ก(block).
- signal() ๋๋ V() ๋๋ up() → ๊ฐ ์ฆ๊ฐ. ๋๊ธฐ ์ค์ธ ์ฐ๋ ๋ ํ๋ ๊นจ์.
์ข ๋ฅ:
- Counting Semaphore: 0 ์ด์ n๊น์ง ๊ฐ ๊ฐ๋ฅ. ์ฌ๋ฌ ๋ฆฌ์์ค ์ ๊ทผ ์ ์ด ๊ฐ๋ฅ.
- Binary Semaphore (์ด์ง ์ธ๋งํฌ์ด): ๊ฐ์ด 0 ๋๋ 1 → ๋ฎคํ ์ค์ฒ๋ผ ์ฌ์ฉ ๊ฐ๋ฅ.
3๏ธโฃ ์ด์ง ์ธ๋งํฌ์ด๋ ๋ฌด์์ธ๊ฐ?
- ์ด์ง ์ธ๋งํฌ์ด = ๊ฐ์ด 0 ๋๋ 1 ๋ง ํ์ฉ.
- ๋ฎคํ
์ค์ ๋งค์ฐ ์ ์ฌ:
- 1์ผ ๋ → lock ๊ฐ๋ฅ
- 0์ผ ๋ → lock๋ ์ํ (wait ๋ฐ์)
- ๋ฎคํ ์ค๋ "์์ ์(owner)" ๊ฐ๋ ์กด์ฌ.
- ์ธ๋งํฌ์ด๋ ๊ทธ๋ฅ ์ผ๋ฐ์ ์ธ counter ๊ธฐ๋ฐ → ๋ฐ๋์ ๋ฝ ์์ ์๊ฐ unlock ํด์ผ ํ๋ค๋ ๊ฐ์ ์ฑ ์์.
4๏ธโฃ ๋ฝ๊ณผ ์ปจ๋์ ๋ณ์๋ฅผ ์ฌ์ฉํ์ฌ ์ธ๋งํฌ์ด๋ฅผ ๋ง๋๋ ๊ฒ์ด ๊ฐ๋ฅํ๊ฐ?
- ์ธ๋งํฌ์ด์ ๋ด๋ถ ์ํ count ๋ณ์๋ฅผ ๋ฝ์ผ๋ก ๋ณดํธ.
- wait() → ๋ฝ ํ๋ ํ count--. count < 0 ์ด๋ฉด ์ปจ๋์ ๋ณ์ wait().
- signal() → ๋ฝ ํ๋ ํ count++. count <= 0 ์ด๋ฉด ์ปจ๋์ ๋ณ์ signal().
→ ์ฆ, ๋ฝ + ์ปจ๋์ ๋ณ์ ์กฐํฉ์ผ๋ก ์ธ๋งํฌ์ด ๊ตฌํ ๊ฐ๋ฅ.
5๏ธโฃ ๊ทธ ๋ฐ๋๋ก ์ธ๋งํฌ์ด๋ฅผ ์ฌ์ฉํ์ฌ ๋ฝ๊ณผ ์กฐ๊ฑด ๋ณ์๋ฅผ ๋ง๋๋ ๊ฒ์ด ๊ฐ๋ฅํ๊ฐ?
๋ฝ: ์ด์ง ์ธ๋งํฌ์ด(๊ฐ์ด 1) ์ฌ์ฉ → lock/unlock ๊ฐ๋ฅ.
์ปจ๋์ ๋ณ์: ๋ถ๋ถ์ ์ผ๋ก ๊ฐ๋ฅํ์ง๋ง ํ๊ณ ์กด์ฌ.
- ์ปจ๋์ ๋ณ์๋ ๋ฝ๊ณผ ํจ๊ป ์ฐ์ด๋ฉฐ "์กฐ๊ฑด"์ ์ฒดํฌ ํ ๊ธฐ๋ค๋ฆฌ๋ ํจํด์ด ์ค์.
- ์ธ๋งํฌ์ด๋ wait() ์ ์กฐ๊ฑด ๋ถ๋ณ์(predicate check) ์์ด ๋ธ๋ก๋๋ฏ๋ก ๋ช ํํ ์๋ฏธ๋ก ์ ์ฐจ์ด ์กด์ฌ.
- ๊ตฌํ์ ๊ฐ๋ฅํ์ง๋ง ์กฐ๊ฑด ๋ณ์์ ์ ํํ ์๋ฏธ๋ก (์: spurious wakeup ๋์ ๋ฑ)์ ์ถฉ์คํ๊ฒ ๋ง์ถ๊ธฐ๋ ์ด๋ ค์.