devWonny 2025. 5. 31. 16:18

๐Ÿ” ๋ฝ๊ณผ ์กฐ๊ฑด๋ณ€์ˆ˜๋ณด๋‹ค ๊ฐ•๋ ฅํ•œ ๋™๊ธฐํ™” ๋„๊ตฌ? ๋ฐ”๋กœ ์„ธ๋งˆํฌ์–ด!

๋ฉ€ํ‹ฐ์“ฐ๋ ˆ๋“œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ํ•˜๋‹ค ๋ณด๋ฉด ์ด๋Ÿฐ ์ƒํ™ฉ์„ ์ž์ฃผ ๋งŒ๋‚˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

  • ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์“ฐ๋ ˆ๋“œ๊ฐ€ ํ•˜๋‚˜์˜ ์ž์›์„ ๋™์‹œ์— ์‚ฌ์šฉํ•˜๋ ค ํ•œ๋‹ค
  • ์–ด๋–ค ์“ฐ๋ ˆ๋“œ๋Š” ํŠน์ • ์กฐ๊ฑด์ด ๋งŒ์กฑ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ ค์•ผ ํ•œ๋‹ค
  • ๋ˆ„๊ฐ€ ๋จผ์ € ์‹คํ–‰๋˜์—ˆ๋А๋ƒ์— ๋”ฐ๋ผ ํ”„๋กœ๊ทธ๋žจ์ด ๊ผฌ์ผ ์ˆ˜ ์žˆ๋‹ค

์ด๋Ÿด ๋•Œ ์šฐ๋ฆฌ๊ฐ€ ํ”ํžˆ ์‚ฌ์šฉํ•˜๋Š” ๋„๊ตฌ๊ฐ€ ๋ฝ(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)

  1. ์„ธ๋งˆํฌ์–ด s์˜ ๊ฐ’์„ 1 ๊ฐ์†Œ
  2. ์ค„์ธ ๊ฒฐ๊ณผ๊ฐ€ 0 ์ด์ƒ์ด๋ฉด, ๊ณ„์† ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  3. ์Œ์ˆ˜๋ฉด, ํ˜„์žฌ ์“ฐ๋ ˆ๋“œ๋Š” ๊ธฐ๋‹ค๋ฆผ(wait/block) ์ƒํƒœ๋กœ ๋“ค์–ด๊ฐ‘๋‹ˆ๋‹ค.

sem_post(&s)

  1. ์„ธ๋งˆํฌ์–ด s์˜ ๊ฐ’์„ 1 ์ฆ๊ฐ€
  2. ์ด๋•Œ ๋Œ€๊ธฐ ์ค‘์ธ ์“ฐ๋ ˆ๋“œ๊ฐ€ ์žˆ๋‹ค๋ฉด, ๊ทธ ์ค‘ ํ•˜๋‚˜๋ฅผ ๊นจ์›๋‹ˆ๋‹ค.

 

 

์ด๊ฑธ ์ด์šฉํ•˜๋ฉด ๋ฝ์ฒ˜๋Ÿผ๋„, ์กฐ๊ฑด๋ณ€์ˆ˜์ฒ˜๋Ÿผ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”.

 

๐Ÿค” ๊ทธ๋Ÿผ ์„ธ๋งˆํฌ์–ด ๊ฐ’์ด ์™œ ์Œ์ˆ˜๊ฐ€ ๋  ์ˆ˜ ์žˆ์ฃ ?

์„ธ๋งˆํฌ์–ด์˜ ๊ฐ’์€ ๋Œ€๊ธฐ ์ค‘์ธ ์“ฐ๋ ˆ๋“œ ์ˆ˜๋ฅผ ๋‚˜ํƒ€๋‚ผ ์ˆ˜๋„ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
์˜ˆ๋ฅผ ๋“ค์–ด:

  • ์ดˆ๊ธฐ๊ฐ’์ด 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์€ ๋Œ€๊ธฐ์— ๋“ค์–ด๊ฐ„๋‹ค.

 

์ด์ง„ ์„ธ๋งˆํฌ์–ด == lock ๊ณผ ๊ฐ™๋„ค์š”

 

 

 


๐Ÿ˜ด ์กฐ๊ฑด ๊ธฐ๋‹ค๋ฆด ๋•Œ๋„ ์„ธ๋งˆํฌ์–ด!

์„ธ๋งˆํฌ์–ด ์ดˆ๊ธฐ๊ฐ’์„ 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 ๋Œ€์‘ ๋“ฑ)์„ ์ถฉ์‹คํ•˜๊ฒŒ ๋งž์ถ”๊ธฐ๋Š” ์–ด๋ ค์›€.