๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๐Ÿฐ42์„œ์šธ

[42seoul] philosophers

Philosophers

Overview

๊ณผ์ œ๋ฅผ ํ•˜๊ธฐ ์ „ ์•Œ์•„์•ผ ํ•  ๊ฒƒ! :

  • ํ•˜๋‚˜ ์ด์ƒ์˜ ์ฒ ํ•™์ž๊ฐ€ ๋‘ฅ๊ทผ ํ…Œ์ด๋ธ”์— ์•‰์•„ ๊ฐ€์šด๋ฐ ์žˆ๋Š” ์ŠคํŒŒ๊ฒŒํ‹ฐ๋ฅผ ๋จน์Œ
  • ์ฒ ํ•™์ž๋Š” eat, think, sleep ์ค‘ ํ•˜๋‚˜์˜ ์ƒํƒœ๋ฅผ ์ทจํ•˜๊ณ  ์žˆ์Œ
  • ์ฒ ํ•™์ž์˜ ์ˆ˜ ๋งŒํผ ํฌํฌ๊ฐ€ ์žˆ์Œ. ๊ผญ ์–‘์†์œผ๋กœ ํฌํฌ ๋‘๊ฐœ๋ฅผ ์žก๊ณ  ๋จน์–ด์•ผ ํ•œ๋Œ€โ€ฆ
  • ์ฒ ํ•™์ž๊ฐ€ eating์„ ๋๋‚ด๋ฉด sleeping ์‹œ์ž‘, ์ผ์–ด๋‚˜๋ฉด thinking ํ•จ. ์ด ์‹œ๋ฎฌ๋ ˆ์ด์…˜์€ ์ฒ ํ•™์ž๊ฐ€ ๊ตถ์–ด ์ฃฝ์œผ๋ฉด ์ข…๋ฃŒ
  • ๋ชจ๋“  ์ฒ ํ•™์ž๋Š” ๋จน์–ด์•ผ ํ•˜๊ณ  ๊ตถ์œผ๋ฉด ์•ˆ๋ผ!
  • ์ฒ ํ•™์ž๋Š” ์„œ๋กœ ์–˜๊ธฐํ•˜์ง€ ์•Š์Œ, ์„œ๋กœ ์ฃฝ์„ ์œ„๊ธฐ์— ์žˆ๋‹ค๋Š” ๊ฒƒ๋„ ๋ชจ๋ฆ„
  • ์ฒ ํ•™์ž๊ฐ€ ์ฃฝ๋Š” ๊ฒƒ์„ ํ”ผํ•˜์ž..

Global rules

  • ์ „์—ญ ๋ณ€์ˆ˜ ๊ธˆ์ง€

  • ํ”„๋กœ๊ทธ๋žจ์ด ์ธ์ž๋กœ ๋ฐ›๋Š” ๊ฒƒ :

    1. number_of_philosophers : ์ฒ ํ•™์ž ์ˆ˜ == ํฌํฌ ๊ฐœ์ˆ˜
    2. time_to_die(๋‹จ์œ„:ms) : ์ด ์‹œ๊ฐ„๋งŒํผ ๋ฐฅ์„ ๋ชป๋จน์œผ๋ฉด ์ฃฝ์Œ
    3. time_to_eat (ms) : ๋จน๋Š”๋ฐ ๊ฑธ๋ฆฌ๋Š” ์‹œ๊ฐ„ (๋จน์„ ๋•Œ ํฌํฌ๋Š” ๊ผญ ๋‘๊ฐœ์”ฉ ์“ด๋Œœโ€ฆ ์™œ๊ทธ๋Ÿฌ๋Š”๊ฒจ๋Œ€์ฒด )
    4. time_to_sleep (ms) : ์ž๋Š”๋ฐ ๊ฑธ๋ฆฌ๋Š” ์‹œ๊ฐ„
    5. number_of_times_each_philosopher_must_eat (optional argument) : ๋ชจ๋“  ์ฒ ํ•™์ž๊ฐ€ ์ฃผ์–ด์ง„ ํšŸ์ˆ˜ ์ด์ƒ ๋ฐฅ์„ ๋จน์œผ๋ฉด ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ์ข…๋ฃŒ. ์ด ์ธ์ž๊ฐ€ ์—†๋‹ค๋ฉด ์ฒ ํ•™์ž๊ฐ€ ์ฃฝ์„ ๋•Œ ์‹œ๋ฎฌ๋ ˆ์ด์…˜์ด ์ข…๋ฃŒํ•จ
  • ๊ฐ ์ฒ ํ•™์ž๋“ค์€ 1 ~ n ์˜ ๋ฒˆํ˜ธ๊ฐ€ ๋งค๊ฒจ์ง. k={1โ‰คkโ‰คn}์ผ๋•Œ, k๋ฒˆ ์ฒ ํ•™์ž๋Š” k-1๊ณผ k+1 ๋ฒˆ ์ฒ ํ•™์ž ์‚ฌ์ด์— ์•‰์Œ

  • ํ”„๋กœ๊ทธ๋žจ์˜ ๋กœ๊ทธ:

  • ์ฒ ํ•™์ž์˜ ์ƒํƒœ ๋ณ€ํ™”๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ ํ˜•์‹์ด์–ด์•ผ ํ•จ

    • timestamp_in_ms X has taken a fork

    • timestamp_in_ms X is eating

    • timestamp_in_ms X is sleeping

    • timestamp_in_ms X is thinking

    • timestamp_in_ms X died

    • timestamp_in_ms๋Š” ํ˜„์žฌ miliseconds, X๋Š” ์ฒ ํ•™์ž ๋ฒˆํ˜ธ*

Mendatory part

mandatory part rule

  • ๊ฐ ์ฒ ํ•™์ž๋Š” ์Šค๋ ˆ๋“œ์ž„
  • ๋‘ ์ฒ ํ•™์ž ์‚ฌ์ด์— ํฌํฌ ํ•˜๋‚˜๊ฐ€ ์กด์žฌ. ์ฒ ํ•™์ž๊ฐ€ ํ•œ๋ช…์ด๋ผ๋ฉด ํฌํฌ๋„ ํ•œ๊ฐœ(์ฃฝ์Œ)
  • ํฌํฌ ์ƒํƒœ๋ฅผ ๋ฎคํ…์Šค๋กœ ๋ณดํ˜ธํ•˜๊ธฐ

Thread

: ํ”„๋กœ์„ธ์Šค ๋‚ด์—์„œ ์‹คํ–‰๋˜๋Š” ์—ฌ๋Ÿฌ ํ๋ฆ„์˜ ๋‹จ์œ„

  • ์Šค๋ ˆ๋“œ๋Š” ํ”„๋กœ์„ธ์Šค ๋‚ด์—์„œ stack๋งŒ ๋”ฐ๋กœ ํ• ๋‹น๋ฐ›๊ณ  code, data, heap ์˜์—ญ์„ ๊ณต์œ ํ•œ๋‹ค.
  • ๋ฉ€ํ‹ฐ ํ”„๋กœ์„ธ์Šค๋ณด๋‹ค ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋”ฉ์ด context switching ๋น„์šฉ์ด ์ ๋‹ค.
  • [๋™๊ธฐํ™”] ๋ฌธ์ œ๋ฅผ ์ฃผ์˜ํ•ด์•ผํ•จ

Synchronization (๋™๊ธฐํ™”)

  • ๋‹ค์ค‘ ํ”„๋กœ์„ธ์Šค ํ˜น์€ ๋‹ค์ค‘ ์Šค๋ ˆ๋“œ๊ฐ€ ํ•˜๋‚˜์˜ ์ž์›์— ์ ‘๊ทผํ•  ๊ฒฝ์šฐ ๋™๊ธฐํ™” ๋ฌธ์ œ ๋ฐœ์ƒ

mandatory ํ—ˆ์šฉ ํ•จ์ˆ˜ ์„ค๋ช…

pthread.h์˜ ํ•จ์ˆ˜๋“ค์„ ์ปดํŒŒ์ผ ํ•  ๋•Œ, -lpthread ํ”Œ๋ž˜๊ทธ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•จ

  • pthread_create : thread๋ฅผ ์ƒ์„ฑ

      int pthread_create(pthread_t *thread, 
                                          const pthread_attr_t *attr,
                                          void *(*start_routine)(void *), 
                                          void *arg);

    return ๊ฐ’ : ์„ฑ๊ณต์ ์œผ๋กœ pthread ๊ฐ€ ๋งŒ๋“ค์–ด์ง„ ๊ฒฝ์šฐ 0์„ ๋ฐ˜ํ™˜ํ•˜๊ณ  thread์— ์‹๋ณ„์ž๋ฅผ ๋‹ด์•„์คŒ

    *thread : thread์˜ ์‹๋ณ„์ž

    *attr : thread์˜ ์†์„ฑ (NULL๋กœ ๋„ฃ์œผ๋ฉด default ์„ค์ •์œผ๋กœ)

    *start_routine : thread๊ฐ€ ์‹คํ–‰ํ•  ํ•จ์ˆ˜ ํฌ์ธํ„ฐ

    *arg : start_routine์— ๋“ค์–ด๊ฐˆ ์ธ์ž

  • pthread_join : ์Šค๋ ˆ๋“œ๊ฐ€ ์ข…๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆผ

      int pthread_join(pthread_t thread, void **value_ptr);

    return ๊ฐ’ : ์„ฑ๊ณต์‹œ 0, ์‹คํŒจ์‹œ ์˜ค๋ฅ˜์ฝ”๋“œ

    void **value_ptr : thread์˜ return value

  • pthread_detach : pthread๋ฅผ ๋ถ€๋ชจ pthread๋กœ๋ถ€ํ„ฐ ๋…๋ฆฝ์‹œํ‚ด

      int pthread_detach(pthread_t thread);

    return ๊ฐ’ : ์„ฑ๊ณต ์‹œ 0, ์˜ค๋ฅ˜์‹œ ์˜ค๋ฅ˜์ฝ”๋“œ

  • thread ์‚ฌ์šฉ ์—ฐ์Šต

      #include <pthread.h>
      #include <stdio.h>
      #include <unistd.h>
    
      void    *routine1(void *arg)
      {
          int num = *(int *)arg;
    
          while (num < 5)
          {
              printf("I'm t1! %d\n", num);
              usleep(30);
              num++;
          }
          printf("t1 finished!\n");
          *(int *)arg =  num;
          return (NULL);
      }
    
      void    *routine2(void *arg)
      {
          int num = *(int *)arg;
    
          while (num < 5)
          {
              printf("I'm t2! %d\n", num);
              usleep(30);
              num++;
          }
          printf("t2 finished!\n");
          *(int *)arg = num;
          return (NULL);
      }
    
      int main(void)
      {
          pthread_t t1;
          pthread_t t2;
    
          int arg1 = 1;
          int arg2 = 1;
    
          pthread_create(&t1, NULL, routine1, (void *)&arg1);
          pthread_create(&t2, NULL, routine2, (void *)&arg2);
          pthread_join(t1, NULL);
          pthread_join(t2, NULL);
          printf("t1 : %d, t2 : %d \n", arg1, arg2);
          return (0);
      }

    โ€”> ์ถœ๋ ฅ๊ฒฐ๊ณผ

      kimjiyoon@gimjiyun-ui-MacBookPro 42Seoul % !.
      ./a.out
      I'm t1! 1
      I'm t2! 1
      I'm t1! 2
      I'm t2! 2
      I'm t1! 3
      I'm t2! 3
      I'm t1! 4
      I'm t2! 4
      t1 finished!
      t2 finished!
      t1 : 5, t2 : 5
  • pthread_mutex_init : mutex ์ดˆ๊ธฐํ™”

      int pthread_mutex_init(pthread_mutex_t * mutex, 
                                           const pthread_mutex_attr *attr);
  • pthread_mutex_destroy : mutex ํŒŒ๊ธฐ or ์ดˆ๊ธฐํ™” ๋˜๊ธฐ ์ „์œผ๋กœ ๋Œ๋ฆฌ๊ธฐ

      int pthread_mutex_destroy(pthread_mutex_t *mutex);

    mutex๋ฅผ destroyํ•˜๊ณ  init์œผ๋กœ ๋‹ค์‹œ ์ดˆ๊ธฐํ™” ํ•ด์ค„ ์ˆ˜ ์žˆ์Œ

  • pthread_mutex_lock : mutex ์ž ๊ธˆ

    pthread_mutex_unlock : mutex ์ž ๊ธˆ ํ•ด์ œ

      int pthread_mutex_lock(pthread_mutex_t *mutex);
      int pthread_mutex_unlock(pthread_mutex_t *mutex);