
์ ๋ฒ ํฌ์คํ ์์ ์์คํ ์์์ ์ฌ๋ฌ ํ๋ก์ธ์ค/์ค๋ ๋๊ฐ ๋์์ ์ ๊ทผํด์ ์ฌ์ฉํ๋ฉด ๋ฐ์ํ ์ ์๋ ๋๊ธฐํ ๋ฌธ์ ์ ๋ํด ์์๋ดค๋๋ฐ, ์ด๋ฌํ ๋๊ธฐํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํ ๊ธฐ๋ฒ์ธ ๋ฎคํ ์ค(Mutex), ์ธ๋งํฌ์ด(Semaphore), ๋ชจ๋ํฐ(Monitor)์ ๋ํด ์์๋ณด๊ณ ๋น๊ตํ๊ณ ์ ํ๋ค.

๋ฎคํ ์ค(Mutex, Mutual Exclusion)๋ ์ํธ ๋ฐฐ์ ๋ฅผ ์๋ฏธํ๋ฉฐ, ํ ๋ฒ์ ํ๋์ ํ๋ก์ธ์ค ๋๋ ์ค๋ ๋๋ง์ด ๊ณต์ ์์์ ์ ๊ทผํ ์ ์๋๋ก ๋ณด์ฅํ๋ ๋๊ธฐํ ๋ฉ์ปค๋์ฆ์ด๋ค. ์ด๋ฅผ ํตํด ์๊ณ ์์ญ(Critical Section)์ ๋ณดํธํ๊ณ ๊ฒฝ์ ์ํ(Race Condition)๋ฅผ ๋ฐฉ์งํ ์ ์๋ค.
๋ฎคํ ์ค๋ ๋ค์๊ณผ ๊ฐ์ ์์๋ก ๊ตฌ์ฑ๋๋ค:

acquire(): ๋ฎคํ
์ค๋ฅผ ํ๋ํ๋ ํจ์.release(): ๋ฎคํ
์ค๋ฅผ ํด์ ํ๋ ํจ์.available: ๋ฎคํ
์ค์ ๊ฐ์ฉ ์ฌ๋ถ๋ฅผ ๋ํ๋ด๋ ๋ถ๋ฆฌ์ธ ๋ณ์.โ๏ธ acquire() ์ release() ๋ ๋ฐ๋์ ์์์ (Atomic)์ผ๋ก ์ํ๋์ด์ผ ํ๋ค.
์์์ ์ฐ์ฐ์ ๋ณด์ฅํ๊ธฐ ์ํด Compare-And-Swap(CAS) ์ฐ์ฐ๊ณผ ๊ฐ์ ํ๋์จ์ด ๋ช ๋ น์ด๋ฅผ ํ์ฉํ ์ ์๋ค. ๋ง์ฝ์ ์ปดํจํฐ๊ฐ ๋จ์ผ ์ฝ์ด๋ผ๋ฉด, ๊ทธ๋ฅ ์ธํฐ๋ฝํธ๋ฅผ Disable ์ํค๋ฉด ๊ฐ๋จํ๋ค.
#include <stdio.h>
#include <pthread.h>
#define ITERATIONS 10000 // ๋ฐ๋ณต ํ์ ์ ์
int sum = 0; // ๊ณต์ ๋ณ์
pthread_mutex_t mutex; // ๋ฎคํ
์ค ์ ์ธ
// ์ค๋ ๋ ํจ์: sum์ ์ฆ๊ฐ์ํค๋ ์ญํ
void *counter(void *param) {
for (int k = 0; k < ITERATIONS; k++) {
// Entry section: ๋ฎคํ
์ค ์ ๊ธ
pthread_mutex_lock(&mutex);
// Critical section: ๊ณต์ ๋ณ์ sum ์ฆ๊ฐ
sum++;
// Exit section: ๋ฎคํ
์ค ์ ๊ธ ํด์
pthread_mutex_unlock(&mutex);
}
pthread_exit(0);
}
int main() {
pthread_t tid1, tid2;
// ๋ฎคํ
์ค ์ด๊ธฐํ
pthread_mutex_init(&mutex, NULL);
// ๋ ๊ฐ์ ์ค๋ ๋ ์์ฑ
pthread_create(&tid1, NULL, counter, NULL);
pthread_create(&tid2, NULL, counter, NULL);
// ์ค๋ ๋๊ฐ ์ข
๋ฃ๋ ๋๊น์ง ๋๊ธฐ
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
printf("sum = %d\n", sum);
// ๋ฎคํ
์ค ์ ๊ฑฐ
pthread_mutex_destroy(&mutex);
return 0;
}
ํ์ง๋ง ๋ฎคํ
์ค๋ฅผ ํ๋ํ์ง ๋ชปํ ํ๋ก์ธ์ค๊ฐ acquire() ํจ์์์ ๋ฌดํ ๋ฃจํ๋ฅผ ๋๋ฉฐ ๊ธฐ๋ค๋ฆฌ๋ ๋ฐ์ ๋๊ธฐ(Busy Waiting) ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์๋ค. ๊ทธ๋ฌ๋ ์ด ๋ฐฉ์์ ์ฅ์ ์ด ๋ ์ ์๋ค. ์ด ์ฅ์ ์ ์ด๋ฆฐ ๋ฐฉ์์ด ์คํ๋ฝ(Spinlock)์ด๋ค.
๋ฎคํ ์ค์ ํ ํํ๋ก ์คํ๋ฝ(Spinlock)์ด ์กด์ฌํ๋ค. ์คํ๋ฝ์ ๋ฎคํ ์ค ์ ๊ธ์ ํ๋ํ ๋๊น์ง ๊ณ์ํด์ CPU๋ฅผ ์ ์ ํ๋ฉด์ ๋ฃจํ๋ฅผ ๋๋ฉฐ ๋๊ธฐํ๋ ๋ฐฉ์์ธ, ์ฆ Busy Waiting์ ํ๋ ๋ฎคํ ์ค์ด๋ค.
์คํ๋ฝ์ ๋ฐ์ ๋๊ธฐ๋ฅผ ์ฌ์ฉํ์ง๋ง ํน์ ์ํฉ์์๋ ํจ์จ์ ์ผ ์ ์๋ค. ๋ฌธ๋งฅ ๊ตํ(Context Switch) ์์ด ๋์ํ๋ฏ๋ก, ์งง์ ์๊ฐ ๋ด์ ๋ฎคํ ์ค๋ฅผ ํ๋ํ ๊ฐ๋ฅ์ฑ์ด ๋์ ๋ ์ ๋ฆฌํ๋ค. ๋ฉํฐ์ฝ์ด ์์คํ ์์๋ ํ๋์ ์ฝ์ด์์ ์ค๋ ๋๊ฐ ๋ฎคํ ์ค๋ฅผ ํด์ ํ๋ ๋์ ๋ค๋ฅธ ์ฝ์ด์์ ๋๊ธฐํ๋ ์ค๋ ๋๊ฐ ๋ฐ๋ก ์คํ๋ ์ ์์ด ์คํ๋ฝ์ด ์คํ๋ ค ๋ ์ข์ ์ ํ์ผ ์ ์๋ค.
๊ทธ๋ฌ๋ ์คํ๋ฝ์ ๋จ์ผ ์ฝ์ด ์์คํ ์์๋ ๋นํจ์จ์ ์ด๋ฏ๋ก, ์ผ๋ฐ์ ์ธ ๋ฉํฐ์ค๋ ๋ ํ๊ฒฝ์์๋ ๋ฐ์ ๋๊ธฐ๋ฅผ ํผํ๊ธฐ ์ํด ์ธ๋งํฌ์ด(Semaphore)๋ ์กฐ๊ฑด ๋ณ์(Condition Variable)์ ๊ฐ์ ๋๊ธฐํ ๊ธฐ๋ฒ์ ์ถ๊ฐ๋ก ํ์ฉํ ์ ์๋ค.

์ธ๋งํฌ์ด๋ Edsger Dijkstra๊ฐ ์ ์ํ ๋๊ธฐํ ๋๊ตฌ๋ก, ๋ฎคํ ์ค์ ๋ฌ๋ฆฌ ๊ณต์ ์์์ ๋์์ ์ ๊ทผํ ์ ์๋ ํ๋ก์ธ์ค๋ ์ค๋ ๋์ ์๋ฅผ ์ ์ดํ ์ ์๋ค. ์ถ์ ๊ฐ๋ฅํ ์๋์ฐจ ์๋ฅผ ๊ด๋ฆฌํ๋ ์ฃผ์ฐจ์ฅ์ด๋ผ๊ณ ์๊ฐํ๋ฉด ๋๋ค.
์ธ๋งํฌ์ด(Semaphore) S๋ ์ ์ํ ๋ณ์์ด๋ฉฐ, ์ด๊ธฐํ ์ดํ์๋ ๋ ๊ฐ์ง ์์์ ์ฐ์ฐ์ธ wait()๊ณผ signal() (ํน์ P()์ V())์ ํตํด์๋ง ์ ๊ทผํ ์ ์๋ค. ์ด๋ P()์ V() ์ฐ์ฐ์ ๊ฐ๊ฐ ๋ค๋๋๋์ด์ธ Proberen(์ํํ๋ค)๊ณผ Verhogen(์ฆ๊ฐํ๋ค)์์ ์ ๋๋์๋๋ฐ, ์ด๋ Edsger Dijkstra๊ฐ ๋ค๋๋๋์ ์ปดํจํฐ ๊ณผํ์๋ผ ๊ทธ๋ ๋ค.
0๊ณผ 1 ์ฌ์ด์์๋ง ๋ณํ๋ฉฐ, 1์ธ ๊ฒฝ์ฐ ๋ฎคํ
์ค์ ์ ์ฌํ๋ค.0 ์ด์์ ๊ฐ์ง ์ ์์ผ๋ฉฐ, ํน์ ๊ฐ์์ ๊ณต์ ์์ ๊ด๋ฆฌ์ ์ฌ์ฉ๋๋ค.Busy - Wait ๋ฐฉ์)์นด์ดํ
์ธ๋งํฌ์ด๋ฅผ ์ด์ฉํ์ฌ ๋ค์ค ์ค๋ ๋ ํ๊ฒฝ์์ ๊ณต์ ๋ณ์ sum ์ ์ ๊ทผํ๋ ์์์ด๋ค.
๋ง์ฝ sem_init ์์ 5 ๋์ 1์ ๋ฃ๋๋ค๋ฉด Binary Semaphore๊ฐ ๋๋ค.
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
int sum = 0; // ๊ณต์ ๋ณ์
sem_t sem;
void *counter(void *param) {
for (int k = 0; k < 10000; k++) {
sem_wait(&sem); // ์ธ๋งํฌ์ด ๊ฐ์ (์ง์
ํ์ฉ ๋๊ธฐ)
sum++;
sem_post(&sem); // ์ธ๋งํฌ์ด ์ฆ๊ฐ (์์ ๋ฐํ)
}
pthread_exit(0);
}
int main() {
pthread_t tid[5]; int i;
sem_init(&sem, 0, 5);
for (i = 0; i < 5; i++)
pthread_create(&tid[i], NULL, counter, NULL);
for (i = 0; i < 5; i++)
pthread_join(tid[i], NULL);
printf("sum = %d\n", sum);
return 0;
}
wait()์ ํธ์ถํ์ฌ ์ธ๋งํฌ์ด ๊ฐ์ ๊ฐ์์ํจ๋ค.signal()์ ํธ์ถํ์ฌ ์ธ๋งํฌ์ด ๊ฐ์ ์ฆ๊ฐ์ํจ๋ค.0์ด ๋๋ฉด, ์ถ๊ฐ์ ์ธ ํ๋ก์ธ์ค๋ ์์์ด ๋ฐํ๋ ๋๊น์ง ๋๊ธฐํ๋ค.๊ธฐ๋ณธ์ ์ธ ์ธ๋งํฌ์ด๋ ๋ฎคํ
์ค์ฒ๋ผ ๋ฐ์ ๋๊ธฐ(Busy Waiting) ๋ฌธ์ ๋ฅผ ๊ฐ์ง ์ ์๋ค. ์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด, Block - Wakeup ๋ฐฉ์์ด ์กด์ฌํ๋ค.
wait() ์ฐ์ฐ์ ์ํํ ํ ์์์ด ์์ผ๋ฉด Busy Waiting์ ํ์ง ์๊ณ (While๋ฌธ ๋์ง ์๊ณ ) ํ๋ก์ธ์ค๋ฅผ ๋๊ธฐ ์ํ๋ก ๋ณ๊ฒฝํ ํ ๋๊ธฐ ํ(Waiting Queue)์ ์ฝ์
ํ๋ค. ์ดํ ๋ค๋ฅธ ํ๋ก์ธ์ค๊ฐ signal() ์ฐ์ฐ์ ํธ์ถํ๋ฉด ๋๊ธฐ ์ค์ธ ํ๋ก์ธ์ค๋ฅผ ๋ค์ ์คํ ๊ฐ๋ฅ ์ํ(Ready Queue)๋ก ์ด๋์ํจ๋ค. ์ด๋ฌํ ๋ฐฉ์์ผ๋ก ๋ฐ์ ๋๊ธฐ(Busy Waiting) ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋ค.
Busy-WaitVSBlock-Wakeup์๊ณ ๊ตฌ์ญ(Critical Section)์ ๊ธธ์ด๊ฐ ๊ธด ๊ฒฝ์ฐ๋
Block-Wakeup๋ฐฉ์์ด ์ ๋ฆฌํ๋ค. ํ์ง๋ง ์๊ณ ๊ตฌ์ญ์ด ์งง๋ค๋ฉด ์ฆ์ ๋ฌธ๋งฅ ๊ตํ์ผ๋ก ์ธํด ์ค๋ฒํค๋๊ฐ ์ฆ๊ฐํ๊ฒ ๋๋ฏ๋กBusy-Wait๋ฐฉ์์ด ์ ๋ฆฌํ๋ค.
์ด์ง ์ธ๋งํฌ์ด(Binary Semaphore)๋ 0๊ณผ 1๋ง ๊ฐ์ง๋ ์ธ๋งํฌ์ด๋ก, ๋จ ํ๋์ ์ค๋ ๋๋ง ์๊ณ ๊ตฌ์ญ(๊ณต์ ์์)์ ์ ๊ทผํ ์ ์๋๋ก ์ ํํ๋ ์ญํ ์ ํ๋ค. ์ฆ, ๋ฎคํ
์ค์ ๊ฐ์ ๊ธฐ๋ฅ์ ์ํํ ์ ์๋ค.
ํ์ง๋ง ๋ฎคํ ์ค๋ ์ธ๋งํฌ์ด์ฒ๋ผ ์ฌ๋ฌ ๊ฐ์ ์ค๋ ๋๊ฐ ๋์์ ์ ๊ทผํ๋๋ก ํ์ฉํ ์ ์๋ค. ๊ทธ๋ ๋ค๋ฉด, ์ ๊ตณ์ด ๋ฎคํ ์ค๋ฅผ ์ฌ์ฉํ ๊น?
์์ ๊ฐ๋ ์ด ์กด์ฌํ๊ธฐ ๋๋ฌธ์ ๋ณด๋ค ์์ ํ ๋๊ธฐํ๊ฐ ๊ฐ๋ฅํ๋ค.
์ธ๋งํฌ์ด๋ ํ ์ค๋ ๋๊ฐ wait()์ ํธ์ถํ์ฌ ์์์ ํ๋ํ ํ, ๋ค๋ฅธ ์ค๋ ๋๊ฐ signal()์ ํธ์ถํ์ฌ ์ด๋ฅผ ํด์ ํ ์๋ ์๋ค. ์ด ๊ฒฝ์ฐ, ํ๋ก๊ทธ๋๋จธ์ ์ค์๋ก ์ธํด ์๋์น ์๊ฒ ์์์ด ํด์ ๋๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์๋ค. ๋ฐ๋ฉด, ๋ฎคํ
์ค๋ ์ด๋ฅผ ํ๋ํ ์ค๋ ๋๋ง์ด ํด์ ํ ์ ์๊ธฐ ๋๋ฌธ์ ์ด๋ฌํ ์ค์๋ฅผ ๋ฐฉ์งํ ์ ์๋ค.
๋ฐ๋๋ฝ(Deadlock) ์ํ์ ์ค์ผ ์ ์๋ค.
์ธ๋งํฌ์ด๋ ์ง์ ์นด์ดํธ๋ฅผ ๊ด๋ฆฌํด์ผ ํ๋ฏ๋ก, wait()์ ์ฌ๋ฌ ๋ฒ ํธ์ถํ๊ณ signal()์ ์ ์ ํ ํธ์ถํ์ง ์์ผ๋ฉด ๋ฐ๋๋ฝ ์ํ์ ๋น ์ง ์ ์๋ค. ๊ทธ๋ฌ๋ ๋ฎคํ
์ค๋ ๋จ์ํ "ํ๋ โก๏ธย ํด์ "์ ํํ๋ก ๋์ํ๋ฏ๋ก ํ๋ก๊ทธ๋๋จธ๊ฐ ์ค์ํ ๊ฐ๋ฅ์ฑ์ด ์ค์ด๋ ๋ค.
๋ช ํํ ์ํธ ๋ฐฐ์ (Mutual Exclusion)๋ฅผ ๋ณด์ฅํ๋ค.
๋ฎคํ ์ค๋ ์๋ ๋ชฉ์ ์ด "ํ๋์ ์ค๋ ๋๋ง ๊ณต์ ์์์ ์ ๊ทผํ๋๋ก ์ ํํ๋ ๊ฒ"์ด๋ฏ๋ก, ๊ณต์ ์์์ ๋ณดํธ์ ์ต์ ํ๋์ด ์๋ค. ๋ฐ๋ฉด, ์ธ๋งํฌ์ด๋ ์ฌ๋ฌ ์ค๋ ๋๊ฐ ์ ๊ทผํ ์ ์๋๋ก ํ์ฉํ๋ ์ฉ๋๋ก ์ค๊ณ๋ ๋งํผ, ๋ฎคํ ์ค๋ฅผ ์ฌ์ฉํด์ผ ํ๋ ์ํฉ์์๋ ์๋ชป ์ ์ฉํ๋ฉด ๋๊ธฐํ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์๋ค.
๋ฎคํ ์ค๊ฐ ๋ณด๋ค ์์ ํ๊ณ ์ง๊ด์ ์ธ ๋๊ธฐํ ๋ฐฉ์์ ์ ๊ณตํ๋ค๋ฉด, ์ธ๋งํฌ์ด๋ ์ ์กด์ฌํ ๊น? ๊ทธ ์ด์ ๋ ์ธ๋งํฌ์ด๊ฐ ๋์ ์ ๊ทผ์ ์ ํํ๋ ๋ฐ ์ ์ฉํ๊ธฐ ๋๋ฌธ์ด๋ค.
์๋ฅผ ๋ค์ด, ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ ํ(DB Connection Pool)๊ณผ ๊ฐ์ ๊ฒฝ์ฐ๋ฅผ ์๊ฐํด๋ณด์. ๋ง์ฝ ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ ์ต๋ 5๊ฐ์ ๋์ ์ฐ๊ฒฐ๋ง ํ์ฉํ๋ค๊ณ ๊ฐ์ ํ๋ฉด, ๋ฎคํ ์ค๋ก๋ ํ๋์ ์ค๋ ๋๋ง ์ ๊ทผํ ์ ์์ด ํจ์จ์ด ๋จ์ด์ง๋ค. ๊ทธ๋ฌ๋ ์ธ๋งํฌ์ด๋ฅผ ์ด์ฉํ๋ฉด 5๊ฐ์ ์ค๋ ๋๊ฐ ๋์์ ์ ๊ทผํ๋๋ก ์ ํํ ์ ์์ด ์์์ ๋ณด๋ค ํจ์จ์ ์ผ๋ก ํ์ฉํ ์ ์๋ค.
๋ํ, IPC์์๋ ์ธ๋งํฌ์ด๋ ์ ์ฉํ๋ค. ๋ฎคํ ์ค๋ ์ผ๋ฐ์ ์ผ๋ก ํ๋์ ํ๋ก์ธ์ค ๋ด์์ ๋์ํ์ง๋ง, ์ธ๋งํฌ์ด๋ ์ฌ๋ฌ ๊ฐ์ ํ๋ก์ธ์ค ๊ฐ ์์ ์ ๊ทผ์ ์กฐ์ ํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
IPC๊ฐ ๊ถ๊ธํ๋ค๋ฉด? ์ฌ๊ธฐ๋ฅผ ํด๋ฆญํ๋ฉด ์์ธํ ์ ์ ์๋ค. ๐ค
์ฆ, ๋ฎคํ ์ค๋ ๋จ์ํ๊ณ ์์ ํ ๋๊ธฐํ๋ฅผ ๋ณด์ฅํ์ง๋ง, ์ฌ๋ฌ ์ค๋ ๋๊ฐ ์ ๊ทผํด์ผ ํ๋ ์ํฉ์์๋ ๋นํจ์จ์ ์ผ ์ ์๋ค. ๋ฐ๋ฉด, ์ธ๋งํฌ์ด๋ ๋ ์ ์ฐํ ๋๊ธฐํ ๋ฐฉ๋ฒ์ ์ ๊ณตํ์ง๋ง, ์ง์ ์นด์ดํธ๋ฅผ ๊ด๋ฆฌํด์ผ ํ๋ฏ๋ก ์ค์ํ ๊ฐ๋ฅ์ฑ์ด ํฌ๋ค. ๋ฌผ๋ก ๋ ๊ธฐ๋ฒ ๋ชจ๋ ์๋ฒฝํ ๋ฐ์ดํฐ ๋ฌด๊ฒฐ์ฑ์ ๋ณด์ฅํ ์ ์๊ณ ๋ฐ๋๋ฝ์ด ๋ฐ์ํ ์ ์๋ค๋ ์ ์ ๊ธฐ์ตํ์.
์ธ๋งํฌ์ด๋ ์ ์ฐํ ๋๊ธฐํ ๋๊ตฌ์ด์ง๋ง, ์คํ ์์๊ฐ ๊นจ์ง๋ ๋ฑ์ ํ์ด๋ฐ ์ค๋ฅ๊ฐ ๋ฐ์ํ ์ ์๋ค. ์๋ฅผ ๋ค์ด,
wait(mutex)์ signal(mutex)์ ์์๋ฅผ ๋ฐ๊พธ๋ฉด ๋๊ธฐํ๊ฐ ๊นจ์ง ์ ์๋ค.signal()๋์ wait()๋ก ์๋ชป ์ฌ์ฉํ๋ฉด ๋ฐ๋๋ฝ์ด ๋ฐ์ํ ์ ์๋ค.wait() ๋๋ signal()์ ์๋ตํ๋ฉด ๊ฒฝ์ ์ํ(race condition)๊ฐ ๋ฐ์ํ ์ ์๋ค.์ด๋ฌํ ๋ฌธ์ ๋ค์ ๋ชจ๋ ๊ฐ๋ฐ์๊ฐ ์ธ๋งํฌ์ด๋ฅผ ์ด๋ป๊ฒ ์ฌ์ฉํ๋๋์ ๋ฐ๋ผ ๋ฐ์ํ๋ค. ์ฆ, ํ๋ก๊ทธ๋๋จธ์ ์ค์๋ก ์ธํด ๋๊ธฐํ ๋ฌธ์ ๋ฅผ ์ผ์ผํฌ ์ ์๋ค๋ ๊ฒ์ด๋ค.
๋ฐ๋ผ์ ์ธ๋งํฌ์ด๋ ์ปค๋ ๋ ๋ฒจ์์ ์ด์์ฒด์ (OS)์ ๋๊ธฐํ ๋ฉ์ปค๋์ฆ์ผ๋ก ์ฌ์ ํ ์ฌ์ฉ๋์ง๋ง, ์ฐ๋ฆฌ๊ฐ ์ ํ๋ ์ ํ๋ฆฌ์ผ์ด์ ๊ฐ๋ฐ ์์ค์์๋ ์ง์ ์ ์ธ ์ธ๋งํฌ์ด๋ณด๋ค๋ ๋ชจ๋ํฐ(Monitor) ๊ธฐ๋ฐ์ ๋๊ธฐํ ๋๊ตฌ๊ฐ ๋ ์ผ๋ฐ์ ์ผ๋ก ์ฌ์ฉ๋๋ค.

๋ชจ๋ํฐ(Monitor)๋ ๋ฎคํ ์ค(Mutex)๋ ์ธ๋งํฌ์ด(Semaphore)์ ๊ฐ์ ์ ์์ค ๋๊ธฐํ ๋ฉ์ปค๋์ฆ์ ์ถ์ํํ์ฌ ๋ ๋์ ์์ค์ ๋๊ธฐํ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ ๊ฐ๋ ์ด๋ค. ์ด๋ ๊ณต์ ์์์ ์๊ณ ๊ตฌ์ญ์ผ๋ก ๊ฐ์ถ๊ณ , ์์์ ์ ๊ทผํ ์ ์๋ ์ธํฐํ์ด์ค๋ง์ ์ ๊ณตํจ์ผ๋ก์จ ๋๊ธฐํ๋ฅผ ๋ณด์ฅํ๋ค. ์ฆ, ํ๋ก์ธ์ค๊ฐ ์ง์ ๋๊ธฐํ ๊ธฐ๋ฒ์ ๋ค๋ฃจ์ง ์๊ณ ๋ ์์ ํ๊ฒ ๊ณต์ ์์์ ์ ๊ทผํ ์ ์๋๋ก ํ๋ค.
๋ชจ๋ํฐ๋ ํ๋ก๊ทธ๋๋จธ๊ฐ ์ ์ํ ์ฐ์ฐ ์งํฉ์ ํฌํจํ๋ ์ถ์ ์๋ฃํ์ผ๋ก, ๋ด๋ถ์์ ์ฌ์ฉํ ์ ์๋ ํน์ ํจ์๋ ๋ฉ์๋๊ฐ ์ ์๋์ด ์๋ค. ์ด๋ฌํ ์ฐ์ฐ๋ค์ ์ํธ ๋ฐฐ์ (Mutual Exclusion)๊ฐ ๋ณด์ฅ๋๋ฏ๋ก, ํ ๋ฒ์ ํ๋์ ํ๋ก์ธ์ค๋ง ๋ชจ๋ํฐ ๋ด๋ถ์ ์ฐ์ฐ์ ์คํํ ์ ์๋ค. ๋ฐ๋ผ์, ๊ฐ๋ฐ์๋ ๋ช ์์ ์ผ๋ก ๋ฝ์ ๊ด๋ฆฌํ ํ์ ์์ด ๋ณด๋ค ์ฝ๊ฒ ์๊ณ ์์ญ์ ๋ณดํธํ ์ ์๋ค.

๊ทธ๋ฌ๋ ๋ชจ๋ํฐ๋ง์ผ๋ก ๋ชจ๋ ๋๊ธฐํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋ ๊ฒ์ ์๋๋ค. ํน์ ์กฐ๊ฑด์ด ์ถฉ์กฑ๋ ๋๊น์ง ํ๋ก์ธ์ค๋ฅผ ๋๊ธฐ ์ํ๋ก ๋ง๋ค๊ธฐ ์ํด ์กฐ๊ฑด ๋ณ์(Condition Variable)๊ฐ ํ์ํ๋ค. ์กฐ๊ฑด ๋ณ์๋ wait()์ signal() ์ฐ์ฐ์ ํตํด ๊ด๋ฆฌ๋๋ค.
condition x, y;
x.wait(); // ํ์ฌ ํ๋ก์ธ์ค๋ฅผ ๋๊ธฐ ์ํ๋ก ์ ํ
x.signal(); // ๋๊ธฐ ์ค์ธ ํ๋ก์ธ์ค๋ฅผ ๊นจ์
wait() : ํ์ฌ ์คํ ์ค์ธ ํ๋ก์ธ์ค๋ฅผ ๋๊ธฐ ์ํ๋ก ์ ํํ๋ค. ์ด๋ ์ธ๋งํฌ์ด์ P() ์ฐ์ฐ๊ณผ ์ ์ฌํ๊ฒ, ์๊ณ ๊ตฌ์ญ์ ์ง์
ํ๋ ค๋ ํ๋ก์ธ์ค๊ฐ ์ ํ ์กฐ๊ฑด์ ๋ง์กฑํ์ง ๋ชปํ ๊ฒฝ์ฐ ๋๊ธฐํ๋๋ก ํ๋ค.signal() : ๋๊ธฐ ์ค์ธ ํ๋ก์ธ์ค๋ฅผ ๊นจ์ ์คํ์ ์ฌ๊ฐํ๋๋ก ํ๋ค. ์ด๋ ์ธ๋งํฌ์ด์ V() ์ฐ์ฐ๊ณผ ์ ์ฌํ๊ฒ ๋์ํ๋ฉฐ, ์๊ณ ๊ตฌ์ญ์ด ๋น์ด ์๋ก์ด ํ๋ก์ธ์ค๊ฐ ์คํ๋ ์ ์๋๋ก ํ๋ค.๊ณต์ ์์์ธ ์ํ ๊ณ์ข ์์ก(balance)์ ๋ณดํธํ๊ธฐ ์ํด ๋ชจ๋ํฐ๋ฅผ ์ฌ์ฉํ๋ ์ฝ๋๋ฅผ ์์๋ก ๋ค์ด๋ณด์.
monitor shared_balance {
private:
int balance = 10;
boolean busy = false;
condition mon;
public:
increase(int amount) {
if (busy == true) mon.wait(); // ์๊ณ ๊ตฌ์ญ์ด ์ฌ์ฉ ์ค์ด๋ฉด ๋๊ธฐ
busy = true; // ์๊ณ ๊ตฌ์ญ ์ง์
balance = balance + amount; // ๊ณต์ ์์ ์์
mon.signal(); // ๋ค์ ๋๊ธฐ ์ค์ธ ํ๋ก์ธ์ค ๊นจ์
}
}
์ด ์ฝ๋์์ increase() ํจ์๋ busy ํ๋๊ทธ๋ฅผ ํ์ธํ์ฌ ์๊ณ ๊ตฌ์ญ์ด ์ฌ์ฉ ์ค์ธ์ง ์ฒดํฌํ๋ค. ๋ง์ฝ ์ด๋ฏธ ๋ค๋ฅธ ํ๋ก์ธ์ค๊ฐ ์๊ณ ๊ตฌ์ญ์ ์ฌ์ฉํ๊ณ ์๋ค๋ฉด, ํ์ฌ ํ๋ก์ธ์ค๋ mon.wait()์ ํธ์ถํ์ฌ ๋๊ธฐ ์ํ๋ก ์ ํ๋๋ค. ๋ฐ๋๋ก, ์๊ณ ๊ตฌ์ญ์ด ๋น์ด ์๋ค๋ฉด busy๋ฅผ true๋ก ์ค์ ํ๊ณ balance๋ฅผ ๊ฐฑ์ ํ ๋ค, mon.signal()์ ํธ์ถํ์ฌ ๋๊ธฐ ์ค์ธ ๋ค๋ฅธ ํ๋ก์ธ์ค๋ฅผ ๊นจ์ด๋ค.
์๋ฅผ ๋ค์ด, ํ๋ก์ธ์ค P1๊ณผ P2๊ฐ increase() ํจ์๋ฅผ ํธ์ถํ๋ค๊ณ ๊ฐ์ ํด๋ณด์. P1์ด ๋จผ์ ์คํ๋๊ณ , balance = balance + amount ์ํ ๋์ค ํ์ ์ฌ๋กฏ์ด ๋๋๊ฒ ๋๋ค๋ฉด, P2๊ฐ increase()๋ฅผ ์คํํ๋ ค๊ณ ์๋ํ ๊ฒ์ด๋ค. ๊ทธ๋ฌ๋ busy๊ฐ true์ด๋ฏ๋ก P2๋ mon.wait()์ ํธ์ถํ๊ณ ๋๊ธฐ ์ํ๋ก ๋ค์ด๊ฐ๋ค. ์ดํ P1์ด ์์
์ ๋ง์น๊ณ mon.signal()์ ํธ์ถํ๋ฉด, P2๊ฐ ๋๊ธฐ ํ์์ ๊นจ์ด๋ ์คํ์ ์ด์ด๊ฐ ์ ์๊ฒ ๋๋ค.
๋ชจ๋ํฐ๋ ์ด๋ฌํ ๋ฐฉ์์ผ๋ก ๋๊ธฐํ๋ฅผ ์๋์ผ๋ก ๊ด๋ฆฌํ๋ฉด์ ๋ถํ์ํ ์ ๋ณด๋ฅผ ์จ๊ธฐ๊ณ , ๊ณต์ ์์์ ๋ํ ๋ช ํํ ์ธํฐํ์ด์ค๋ง์ ์ ๊ณตํ๋ค. ์ด๋ ๊ฐ์ฒด ์งํฅ ํ๋ก๊ทธ๋๋ฐ์์์ ์ ๋ณด ์๋(Information Hiding) ๊ฐ๋ ๊ณผ๋ ์ ์ฌํ๋ค.
๋จผ์ , ๋ฎคํ ์ค๋ ์ฌ๋ฌ ํ๋ก์ธ์ค๋ ์ค๋ ๋ ๊ฐ ๋๊ธฐํ๋ฅผ ์ํด ์ฌ์ฉ๋๋ค. ์ฆ, ์ด์์ฒด์ ์ปค๋์ด ์ ๊ณตํ๋ ๋ฝ(Lock) ๋ฉ์ปค๋์ฆ์ผ๋ก, ์๋ก ๋ค๋ฅธ ํ๋ก์ธ์ค์์๋ ๊ณต์ ์์์ ์์ ํ๊ฒ ๋ณดํธํ ์ ์๋ค. ํ์ง๋ง ์ด์์ฒด์ ์ฐจ์์ ๋๊ธฐํ ๊ธฐ๋ฅ์ด๊ธฐ ๋๋ฌธ์ ๋ฌด๊ฒ๊ณ ์ฑ๋ฅ์ด ๋ค์ ๋๋ฆฌ๋ค๋ ๋จ์ ์ด ์๋ค.
๋ฐ๋ฉด, ๋ชจ๋ํฐ๋ ํ๋์ ํ๋ก์ธ์ค ๋ด์์ ์ค๋ ๋ ๊ฐ ๋๊ธฐํ๋ฅผ ์ํด ์ ๊ณต๋๋ค. ์ด์์ฒด์ ์์ค์ด ์๋๋ผ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด๋ ํ๋ ์์ํฌ์์ ์ ๊ณตํ๋ ๋๊ธฐํ ๊ธฐ๋ฅ์ด๋ฉฐ, ๋ด๋ถ์ ์ผ๋ก ๋ฎคํ
์ค๋ฅผ ํ์ฉํ์ง๋ง ๋ ๋์ ์์ค์ ์ถ์ํ๋ ๊ฐ๋
์ด๋ค. ๋ํ์ ์ธ ์๋ก Java์์ synchronized, wait(), notify() ๋ฑ์ ์ด์ฉํ ๋๊ธฐํ ๋ฐฉ์์ด ์๋ค.
์ฆ, ๋ชจ๋ํฐ๋ ๋ฎคํ ์ค์ ์์ ๊ฐ๋ ์ผ๋ก ๋ณผ ์ ์์ผ๋ฉฐ, ํ๋ก๊ทธ๋๋จธ๊ฐ ์ง์ ๋ฝ์ ๊ด๋ฆฌํ ํ์ ์์ด ๋ ์ฝ๊ฒ ๋๊ธฐํํ ์ ์๋๋ก ๋์์ค๋ค. ๋ฐ๋ผ์ ๋ฎคํ ์ค๋ ์ปค๋ ๋จ์์ ๋์ํ๋ ๋ฌด๊ฒ์ง๋ง ๊ฐ๋ ฅํ ๋๊ธฐํ ๋ฐฉ์์ด๊ณ , ๋ชจ๋ํฐ๋ ์ธ์ด ์ฐจ์์์ ์ ๊ณต๋๋ ๋ ๊ฐ๋ณ๊ณ ํธ๋ฆฌํ ๋๊ธฐํ ๋๊ตฌ๋ผ๊ณ ๋ณผ ์ ์๋ค.
์ธ๋งํฌ์ด๋ ์นด์ดํฐ ๊ธฐ๋ฐ ๋๊ธฐํ ๊ธฐ๋ฒ์ผ๋ก, ๊ฐ๋ฐ์๊ฐ ์ง์ ๊ฐ์ ์ค์ ํด์ผ ํ๋ค. ํ์ง๋ง ํ๋ก๊ทธ๋๋จธ๊ฐ ์ง์ wait()๊ณผ signal()์ ์ฌ์ฉํด ์นด์ดํธ ๊ฐ์ ์กฐ์ํด์ผ ํ๋ฏ๋ก ๊ด๋ฆฌ๊ฐ ๋ฒ๊ฑฐ๋ก์ธ ์ ์๋ค.
๋ฐ๋ฉด, ๋ชจ๋ํฐ๋ ๋ด๋ถ์ ์ผ๋ก ๋๊ธฐํ ๋ฉ์ปค๋์ฆ์ ์บก์ํํ์ฌ ๊ฐ๋ฐ์๊ฐ ์ง์ ๋ฝ์ ๊ด๋ฆฌํ ํ์๊ฐ ์๋ค. Java์์๋ ๋ชจ๋ ๊ฐ์ฒด๊ฐ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ชจ๋ํฐ๋ฅผ ์ ๊ณตํ๋ฉฐ, synchronized ํค์๋๋ฅผ ์ฌ์ฉํ๋ฉด ์๋์ผ๋ก ๋ฝ์ ํ๋ํ๊ณ ํด์ ํ๋ ๊ธฐ๋ฅ์ ์ํํ๋ค. ๋ํ, wait(), notify(), notifyAll() ๊ฐ์ ๋ฉ์๋๋ฅผ ํ์ฉํ๋ฉด ์ค๋ ๋ ๊ฐ์ ํ๋ ฅ์ ์ธ ๋๊ธฐํ๊ฐ ๊ฐ๋ฅํ๋ค.
๋ํ, ๋ชจ๋ํฐ๋ ํ๋์ ํ๋ก์ธ์ค ๋ด์์๋ง ๋์ํ๋ ๋ฐ๋ฉด, ์ธ๋งํฌ์ด๋ ๋ค์ค ํ๋ก์ธ์ค ํ๊ฒฝ์์๋ ์ฌ์ฉ๋ ์ ์๋ค๋ ์ฐจ์ด์ ์ด ์๋ค. ์ฆ, ๋ชจ๋ํฐ๋ ๊ธฐ๋ณธ์ ์ผ๋ก ๋จ์ผ ํ๋ก์ธ์ค์ ์ค๋ ๋ ๋๊ธฐํ์ ์ด์ ์ ๋ง์ถ๊ณ ์์ผ๋ฉฐ, ์ธ๋งํฌ์ด๋ ์ด์์ฒด์ ์ฐจ์์์ ํ๋ก์ธ์ค ๊ฐ ๋๊ธฐํ(IPC)๊น์ง ์ง์ํ ์ ์๋ค.
synchronized ํค์๋synchronized (object) { // ์๊ณ์์ญ }public synchronized void method() {}wait()์ notify() ๋ฉ์๋wait(): ํ์ฌ ์ค๋ ๋ ๋๊ธฐ ์ํ๋ก ๋ง๋ฆnotify(): ๋๊ธฐ ์ค์ธ ์ค๋ ๋ ์ค ํ๋๋ฅผ ๊นจ์notifyAll(): ๋๊ธฐ ์ค์ธ ๋ชจ๋ ์ค๋ ๋๋ฅผ ๊นจ์๋ผ์ด๋ธ๋์ค(Liveness)๋ ํ๋ก์ธ์ค๊ฐ ์ธ์ ๊ฐ๋ ๋ฐ๋์ ์งํ๋ ์ ์์์ ๋ณด์ฅํ๋ ์ฑ์ง์ ์๋ฏธํ๋ค. ์ฆ, ์์คํ ์ด ๊ต์ฐฉ ์ํ(Deadlock)๋ ๋ฌดํ ๋๊ธฐ(Starvation) ์์ด ์ ์์ ์ผ๋ก ์คํ๋๋๋ก ํ๋ ๊ฐ๋ ์ด๋ค.
+) ์ธ๋งํฌ์ด๋ ๋ชจ๋ํฐ๋ ๋ฐ๋๋ฝ๊ณผ ๊ธฐ์ ํ์์ ํด๊ฒฐํด์ฃผ์ง ๋ชปํ๋ค.
๋ฐ๋๋ฝ(Deadlock)
- ๋ ๊ฐ ์ด์์ ํ๋ก์ธ์ค๊ฐ ์๋ก์ ์์์ ๊ธฐ๋ค๋ฆฌ๋ฉด์ ์์ํ ๋ฉ์ถ๋ ์ํ
์ฐ์ ์์ ์ญ์ (Priority Inversion)
- ๋ฎ์ ์ฐ์ ์์ ํ๋ก์ธ์ค๊ฐ ์์์ ์ ์ ํ๋ฉด์ ๋์ ์ฐ์ ์์ ํ๋ก์ธ์ค๊ฐ ๋๊ธฐ
[์ง๊ธ ๋ฌด๋ฃ]์ด์์ฒด์ ๊ณต๋ฃก์ฑ ๊ฐ์ ๊ฐ์ | ์ฃผ๋์จ - ์ธํ๋ฐ
[์ด์์ฒด์ ] ์ธ๋งํฌ์ด(semaphore) ๋ฎคํ ์ค(mutex) ๋ชจ๋ํฐ(Monitor)
์ด์ฌํ ์ฝ์๋๋ฐ ๋ญ์๋ฆฐ์ง๋ฅผ ๋ํต ๋ชจ๋ฅด๊ฒ ๊ตฐ์.. ์ฃ์กํฉ๋๋ค.. ํ๋ก์ธ์ค ์ค๋ ๋๋ ์ ์ฝ์์ด์..