º´·Ä ÇÁ·Î±×·¡¹Ö
ÃÑ ÆäÀÌÁö ¼ö : 3224

Àüü ÇÔ¼ö/¿ë¾î»çÀü
Facebook Joinc ±×·ì   Joinc QA »çÀÌÆ®



joinc´Â Firefox¿Í chrome¿¡¼­ Å×½ºÆ® Çß½À´Ï´Ù. IE¿¡¼­´Â Å×À̺íÀÌ ±úÁö°Å³ª À̹ÌÁö°¡ º¸ÀÌÁö ¾ÊÀ» ¼ö ÀÖ½À´Ï´Ù. ƯÈ÷ ±¸±Û DocsÀ̹ÌÁöÀÇ °æ¿ì ¿¢¹Úó¸®µÉ ¼ö ÀÖ½À´Ï´Ù.

º´·Ä ÇÁ·Î±×·¡¹Ö

Multi Thread, Mutl Processor, concurrency - parallel ÇÁ·Î±×·¡¹Ö °ü·ÃµÈ ³»¿ëÀ» Á¤¸®Á» ÇØºÁ¾ß °Ú´Ù.


POSIX ¿Í Thread-safety

ÀçÁøÀÔ

POSIX.1¿¡ ±â¹ÝÇÑ C¾ð¾î ÇÔ¼öµéÀº ´ÜÀÏ ¾²·¹µå ÇÁ·Î¼¼½º ȯ°æÀ» °¡Á¤ÇÏ°í ¸¸µé¾îÁ³´Ù. ÀçÁøÀÔ(Reentrancy)´Â µðÀÚÀÎ À̽´°¡ ¾Æ´Ï¾ú´Ù. ±×·¯¹Ç·Î ¸ÖƼ ¾²·¹µå ÇÁ·Î±×·¡¹Ö ȯ°æ¿¡¼­ POSIX ÇÔ¼ö°¡ ÀçÁøÀÔ °¡´ÉÇÒÁö¸¦ º¸ÀåÇÒ ¼ö ¾ø´Ù. ¸ÖƼ ¾²·¹µå ȯ°æ¿¡¼­´Â »ç¿ëÇÏ·Á´Â ÇÔ¼ö°¡ ÀçÁøÀÔ°¡´ÉÇÑÁö¸¦ °ËÅäÇØ¾ß ÇÑ´Ù.

¿¹¸¦ µé¾î¼­ asctimeÇÔ¼ö´Â ÇÁ·Î¼¼½ºÀÇ ¸Þ¸ð¸®¿µ¿ª¿¡ °ø°£À» ÇÒ´çÇϰí, ±×¿¡ ´ëÇÑ Æ÷ÀÎÅ͸¦ µ¹·ÁÁØ´Ù. µ¥ÀÌÅÍ ¿µ¿ªÀÌ µ¶¸³ÀûÀÌÁö ¾Ê±â ¶§¹®¿¡ ´Ù¸¥ ¾²·¹µå¿¡¼­ asctimeÇÔ¼ö¸¦ È£ÃâÇϸé, ÇÁ·Î¼¼½º µ¥ÀÌÅͰ¡ º¯ÇØ ¹ö¸®´Â ¹®Á¦°¡ ¹ß»ýÇÑ´Ù.
001  #include <stdio.h>
002  #include <unistd.h>
003  #include <stdlib.h>
004  #include <pthread.h>
005  #include <time.h>
006  
007  #define MAX_THREAD_NUM  1
008  void *t_function(void *data)
009  {
010      time_t current_time ;
011      struct tm *mytm;
012      char *time_str;
013  
014      current_time = time((time_t *)NULL);
015      mytm = localtime(¤t_time);
016  
017      time_str = asctime(mytm);
018      printf("Child Thread Start Time : %s", time_str);
019      sleep(5);
020  }
021  
022  int main(int argc, char **argv)
023  {
024      pthread_t p_thread[2];
025      int thr_id;
026      int status;
027      int i = 0;
028      time_t current_time ;
029      struct tm *mytm;
030      char *time_str;
031  
032      current_time = time((time_t *)NULL);
033      mytm = localtime(¤t_time);
034      time_str = asctime(mytm);
035      printf("Main Thread Start Time 1 : %s", time_str);
036      sleep(10);
037  
038      for( i = 0; i < MAX_THREAD_NUM; i++)
039      {
040          thr_id = pthread_create(&p_thread[i], NULL, t_function, (void *)&i);
041          if (thr_id < 0)
042          {
043              perror("thread create error : ");
044              exit(0);
045          }
046      }
047      pthread_join(p_thread[0], NULL);
048      printf("Main Thread Start Time 2 : %s", time_str);
049      return 0;
050  }
051  
¸ÖƼ ¾²·¹µå ÇÁ·Î±×·¥¿¡¼­, ÀçÁøÀÔÀ» º¸ÀåÇÏÁö ¾Ê´Â ÇÔ¼ö¸¦ »ç¿ëÇßÀ» ¶§ ¹ß»ýÇÏ´Â ¹®Á¦¸¦ º¸¿©ÁÖ°í ÀÖ´Ù. 018°ú 048¿¡¼­ time_strÀÇ Ãâ·Â°á°ú°¡ ´Ù¸£´Ù. t_function ¾²·¹µåÇÔ¼ö¿¡¼­ asctimeÀ» È£ÃâÇϸ鼭 ¸Þ¸ð¸® ÇÒ´çµÈ ¿µ¿ªÀÇ µ¥ÀÌÅ͸¦ º¯°æÇØ ¹ö·È±â ¶§¹®ÀÌ´Ù.

´ÙÀ½Àº ÀçÁøÀÔÇÏÁö ¾Ê´Â ÇÔ¼öµéÀÌ´Ù.
ÀÌ ¹®Á¦¸¦ ÇØ°á Çϱâ À§Çؼ­ ÀçÁøÀÔ °¡´ÉÇÑ º°µµÀÇ ÇÔ¼ö¸¦ »ç¿ëÇØ¾ß ÇÑ´Ù. ÇÔ¼ö¿¡ _rÀÌ ºÙÀº ÇÔ¼ö´Â ÀçÁøÀÔ °¡´ÉÇÑ ¹öÀüÀÇ ÇÔ¼öÀÓÀ» ÀǹÌÇÑ´Ù. asctimeÇÔ¼öÀÇ ÀçÁøÀÔ °¡´ÉÇÑ ÇÔ¼ö´Â asctime_rÇÔ¼ö´Ù. ´ç¿¬È÷ ¸ÖƼ ¾²·¹µå ÇÁ·Î±×·¡¹Ö¿¡¼­´Â _rÀÌ ºÙÀº À̸§ÀÇ ÇÔ¼ö¸¦ »ç¿ëÇØ¾ß ÇÑ´Ù.

errno

errno´Â external Àü¿ª º¯¼ö´Ù. ±×·¯¹Ç·Î ¸ÖƼ ¾²·¹µå ȯ°æ¿¡¼­ ¿¡·¯¸¦ °Ë»çÇϱâ À§ÇÑ ¸ñÀûÀ¸·Î »ç¿ëÇϱâ Èûµé´Ù. ÃÖ±Ù¿¡ È£ÃâÇÑ ÇÔ¼öÀÇ errno°ªÀÎÁö¸¦ Àå´ãÇÒ ¼ö ¾ø±â ¶§¹®ÀÌ´Ù.

ÀçÁøÀÔÀ» º¸ÀåÇϱâ À§ÇÑ ¹æ¹ý

  1. ÀçÁøÀÔ °¡´ÉÇÑ ¹öÀüÀÇ ÇÔ¼ö Áï, _rÀÌ ºÙÀº ÇÔ¼ö¸¦ »ç¿ëÇÑ´Ù.
  2. ¹ÂÅØ½ºµîÀ¸·Î Àü¿ª µ¥ÀÌÅÍ¿¡ ´ëÇÑ Á¢±ÙÀ» Á¦¾îÇÑ´Ù.
  3. gccÀÇ °æ¿ì _REENTRANT Á¤ÀÇÇØ¼­ ÀçÁøÀÔÀ» º¸ÀåÇÒ ¼ö ÀÖ´Ù. ÀçÁøÀÔ °¡´ÉÇÑ ÇÔ¼ö¿Í ±×·¸Áö ¾ÊÀº ÇÔ¼ö°¡ Á¸Àç ÇÒ¶§, ÀçÁøÀÔ °¡´ÉÇÑ ÇÔ¼ö¸¦ ¸µÅ©ÇÑ´Ù. ¶ÇÇÑ errno¿Í °°Àº external Àü¿ª º¯¼ö¸¦ °¢ ¾²·¹µå ¸¶´Ù »ç¿ëÇÒ ¼ö ÀÖµµ·Ï ÇØÁØ´Ù.

    # gcc -o myprog myprog.c -lpthread -D_REENTRANT 
     

ÀçÁøÀÔ °¡´ÉÇÑ »ç¿ëÀÚ Á¤ÀÇ ÇÔ¼ö ¸¸µé±â

¾Æ·¡ÀÇ ¿øÄ¢À» ÁöÄÑ¾ß ÇÑ´Ù.
  1. Àü¿ªº¯¼ö¸¦ »ç¿ëÇÏÁö ¾Ê´Â´Ù.
  2. Àü¿ªº¯¼öÀÇ Æ÷ÀÎÅ͸¦ ¹ÝȯÇÏÁö ¾Ê´Â´Ù. ´ë½Å ÀÎÀÚ·Î µ¥ÀÌÅ͸¦ ³Ñ°Ü¹Þµµ·Ï ÇÑ´Ù. POSIXÀÇ _r°è¿­ ÇÔ¼ö°¡ ÀÌ·± ¹æ½ÄÀ» »ç¿ëÇÑ´Ù.
  3. °øÀ¯µÇ´Â ÀÚ¿øÀº Á¢±ÙÁ¦¾î¸¦ ÇÑ´Ù.
  4. ÀçÁøÀÔÇÏÁö ¾Ê´Â ÇÔ¼ö´Â È£ÃâÇÏÁö ¾Ê´Â´Ù.
  5. µ¥ÀÌÅÍ °ø°£À» ÇÔ¼ö°¡ ¾Æ´Ñ È£ÃâÀÚ°¡ Á¦°øÇϵµ·Ï ÇÑ´Ù.

º´·Ä ÇÁ·Î±×·¡¹Ö¿¡¼­ ÁÖÀÇ ÇØ¾ßÇÒ ¹®Á¦µé

ABA ¹®Á¦

A ¾²·¹µå¿Í B ¾²·¹µå°¡ ÀÖ´Ù.
  1. A ¾²·¹µå°¡ ¸Þ¸ð¸®ÀÇ °ªÀ» Àд´Ù. ÀÌ·± Àú·± ¿¬»êÀ» ÇÑ´Ù.
  2. B ¾²·¹µå°¡ ¸Þ¸ð¸®ÀÇ °ªÀ» Àд´Ù. ÀÌ·± Àú·± ¿¬»êÀ» ÇÑ´Ù.
  3. A ¾²·¹µå°¡ ¸Þ¸ð¸®¿¡ ¿¬»ê °ªÀ» ¾´´Ù.
  4. B ¾²·¹µå°¡ ¸Þ¸ð¸®¿¡ ¿¬»ê °ªÀ» ¾´´Ù.
À̸¦ ABA ¹®Á¦¶ó°í ÇÑ´Ù. Á¤»óÀûÀ¸·Î ¿¬»êÀÌ µÇ·Á¸é, ´ÙÀ½°ú °°Àº È帧À» °¡Á®¾ß ÇÑ´Ù.
  1. A ¾²·¹µå°¡ ¸Þ¸ð¸®ÀÇ °ªÀ» Àд´Ù. ÀÌ·± Àú·± ¿¬»êÀ» ÇÑ´Ù.
  2. A ¾²·¹µå°¡ ¿¬»ê °ªÀ» ¸Þ¸ð¸®¿¡ ¾´´Ù.
  3. B ¾²·¹µå°¡ ¸Þ¸ð¸®ÀÇ °ªÀ» Àд´Ù. ÀÌ·± Àú·± ¿¬»êÀ» ÇÑ´Ù.
  4. B ¾²·¹µå°¡ ¸Þ¸ð¸®¿¡ ¿©»ê °ªÀ» ¾´´Ù.
ÀÌ ¹®Á¦´Â ¼¼¸¶Æ÷¾î³ª ¹ÂÅØ½ºµîÀ¸·Î ÀӰ迵¿ª¿¡ ´ëÇÑ Á¢±ÙÀ» Á¦¾îÇÏ´Â °ÍÀ¸·Î ÇØ°áÇÒ ¼ö ÀÖ´Ù.

killer-tolerance

Àá±ÝÀ» ¾òÀº ¾²·¹µå°¡ ¾î¶² ÀÌÀ¯·Î Àá±ÝÀ» Ç®Áö ¾Ê°í Á¾·áµÇ´õ¶óµµ ´Ù¸¥ ¾²·¹µå¿¡ ¿µÇâÀ» ¹ÌÄ¡¸é ¾ÈµÈ´Ù. Áï ½º·¹µå°¡ Á×À¸¸é ÀÚµ¿ÀûÀ¸·Î Àá±ÝÀ» µ¹·ÁÁà¾ß ÇÑ´Ù. ¸¸¾à pthread¿ì¤Ò mutex¸¦ ÀÌ¿ëÇØ¼­ Àá±ÝÀ» »ý¼ºÇß´Ù¸é, killer-tolerance¸¦ °ÆÁ¤ÇÒ Çʿ䰡 ¾ø´Ù. ¾Ë¾Æ¼­ ÇØÁ¦ ½ÃÄÑÁֱ⠶§¹®ÀÌ´Ù. ´ÙÀ½ÀÇ Äڵ带 Å×½ºÆ® ÇØº¸ÀÚ.
#include <stdio.h>   
#include <unistd.h>   
#include <pthread.h>   
  
int ncount;    // ¾²·¹µå°£ °øÀ¯µÇ´Â ÀÚ¿ø  
pthread_mutex_t  mutex = PTHREAD_MUTEX_INITIALIZER; // ¾²·¹µå ÃʱâÈ­  
  
void* do_loop(void *data)  
{  
    int i;  
    for (i = 0; i < 10; i++)  
    {  
        pthread_mutex_lock(&mutex); // Àá±ÝÀ» »ý¼ºÇÑ´Ù.  
        printf("loop1 : %d\n", ncount);  
        ncount ++;  
        if(i == 10) return;           // Àá±ÝÀ» Ç®Áö ¾Ê°í ½º·¹µå¸¦ Á¾·áÇÑ´Ù. 
        pthread_mutex_unlock(&mutex); // Àá±ÝÀ» ÇØÁ¦ÇÑ´Ù.  
        sleep(1);  
    }  
}  
  
void* do_loop2(void *data)  
{  
    int i;  
  
    // Àá±ÝÀ» ¾òÀ¸·Á°í ÇÏÁö¸¸ do_loop ¿¡¼­ ÀÌ¹Ì Àá±ÝÀ»   
    // ¾ò¾úÀ½À¸·Î Àá±ÝÀÌ ÇØÁ¦µÉ¶§±îÁö ±â´Ù¸°´Ù.    
    for (i = 0; i < 10; i++)  
    {  
        pthread_mutex_lock(&mutex); // Àá±ÝÀ» »ý¼ºÇÑ´Ù.  
        printf("loop2 : %d\n", ncount);  
        ncount ++;  
        pthread_mutex_unlock(&mutex); // Àá±ÝÀ» ÇØÁ¦ÇÑ´Ù.  
        sleep(2);  
    }  
}      
  
int main()  
{  
    int       thr_id;  
    pthread_t p_thread[2];  
    int status;  
    int a = 1;  
 ` 
    ncount = 0;  
    thr_id = pthread_create(&p_thread[0], NULL, do_loop, (void *)&a);  
    sleep(1);  
    thr_id = pthread_create(&p_thread[1], NULL, do_loop2, (void *)&a);  
  
    pthread_join(p_thread[0], (void *) &status);  
    pthread_join(p_thread[1], (void *) &status);  
  
    status = pthread_mutex_destroy(&mutex);  
    printf("code  =  %d", status);  
    printf("programing is end");  
    return 0;  
}  
 

¼¼¸¶Æ÷¾î¸¦ »ç¿ëÇÒ ¶§, ȤÀº ÆÄÀÏ Àá±ÝÀ̳ª ±âŸ IPC¸¦ »ç¿ëÇÒ ¶§ ¾²·¹µåÀÇ Á¾·á°¡ Àá±Ý¿¡ ¹ÌÄ¡´Â ¿µÇâ¿¡ ´ëÇØ¼­ ÃæºÐÈ÷ °í·ÁÇØ¾ß ÇÑ´Ù.

async-signal-safety

ƯÁ¤ ÇÔ¼ö A°¡ Àá±ÝÀ» ¾òÀº »óÅ¿¡¼­, ½Ã±×³ÎÀÌ ¹ß»ýÇØ¼­ ½Ã±×³Î Çڵ鷯°¡ ½ÇÇàµÆ´Ù. ±×·±µ¥, ½Ã±×³Î Çڵ鷯°¡ ÇÔ¼ö A¸¦ ´Ù½Ã È£ÃâÇÑ´Ù¸é, ¶ôÀ» ¾òÀº »óÅ¿¡¼­ ´Ù½Ã ¶ôÀ» ¾òÀ»·Á°í ½ÇÇàÇϱ⠶§¹®¿¡ ¿µ¿øÈ÷ ºÀ¼âµÉ °ÍÀÌ´Ù. ÀÌ·± °æ¿ì°¡ ÀÚÁÖ ¹ß»ýÇÒ °Í °°Áö´Â ¾Ê´Ù. ±×³É »ó½ÄÀûÀ¸·Î ½Ã±×³Î Çڵ鷯°¡ ÀÚ½ÅÀ» È£ÃâÇÑ ÇÔ¼ö¸¦ È£ÃâÇÏÁö ¾Êµµ·Ï ÀÛ¼ºÇϸé ÀÌ ¹®Á¦¸¦ ȸÇÇÇÒ ¼ö ÀÖÀ» °ÍÀÌ´Ù.


preemption-tolerance

Àá±ÝÀ» ¾òÀº ½º·¹µå°¡ ÈÞ¸é»óÅ¿¡ ÀÖÀ» ¶§, ´Ù¸¥ ½º·¹µå¿¡ ¿µÇâÀ» ¹ÌÄ¡¸é ¾ÈµÈ´Ù. ´ÙºÐÈ÷ ³í¸®ÀûÀÎ ¹®Á¦¶ó°í ÇÒ ¼ö ÀÖ´Ù. Áï ½º·¹µå´Â ¸¶¶¥È÷ ÈÞ¸é»óÅ¿¡ ÀÖ¾î¾ß ÇÒ¶§, ÈÞ¸é »óÅ¿¡ ³õ¿©¾ß ÇÑ´Ù. ÇÏÁö¸¸ Àá±ÝÀ» ¾òÀº »óÅ¿¡¼­ ¿À·£ ½Ã°£ ÀӰ迵¿ª¿¡ ¸Ó¹«¸£´Â °ÍÀº ¹Ù¶÷Á÷ÇÏÁö ¾ÊÀ» °ÍÀÌ´Ù.

processor heap

¸Þ¸ð¸®¸¦ ÇÒ´ç ÇÒ¶§, ÇÁ·Î¼¼½ºÀÇ heap¿µ¿ªÀ» »ç¿ëÇÏ´Â °ÍÀº Áö¾çÇÏÀÚ. ÇÁ·Î¼¼½ºÀÇ heapÀ» »ç¿ëÇÒ °æ¿ì false sharing ¹®Á¦°¡ ¹ß»ýÇÒ ¼ö ÀÖ´Ù. ¶ÇÇÑ ÀÚ¿ø °øÀ¯¸¦ À§ÇÑ ¶ô¿¡´Â ¸¹Àº ºñ¿ëÀÌ µé¾î°£´Ù.

false sharing

¸ÖƼ ÄÚ¾î CPU¿¡¼­ ¹ß»ýÇÒ ¼ö ÀÖ´Â ¹®Á¦´Ù. ¸ÖƼ ÄÚ¾î CPU¿¡¼­´Â µ¥ÀÌÅ͸¦ word ´ÜÀ§·Î Àоî¿À´Â ´ë½Å ¸Þ¸ð¸® I/O È¿À²¼ºÀ» À§Çؼ­ cache-line·Î Àоî¿À´Âµ¥, ÀÌ´ë ¹®Á¦°¡ »ý±æ ¼ö ÀÖ´Ù. µÎ°³ÀÇ ¸Þ¸ð¸® ¿¬»êÀÌ µ¿ÀÏÇÑ Ä³½¬¶óÀο¡¼­ ½ÇÇàµÉ °æ¿ì, CPU<->Memory ¹ö½º »çÀÌ¿¡¼­ Çϵå¿þ¾îÀûÀÎ ¶ôÀÌ °É¸®´Âµ¥, À̶§ Çϵå¿þ¾îÀûÀÎ º´¸ñÇö»óÀÌ ¹ß»ýÇÑ´Ù.

´ÙÀ½°ú °°Àº ¹æ¹ýÀ¸·Î ÇØ°áÇÒ ¼ö ÀÖ´Ù.
  • OS°¡ °ü¸®ÇØÁÖ´Â ¸Þ¸ð¸® ´ÜÀ§ÀÎ ÆäÀÌÁö¿¡¼­ °°ÀÌ ¾²´Â µ¥ÀÌÅͰ¡ °°ÀÌ ¿Ã¶ó°¡µµ·Ï ÇÒ °Í.
  • ¼­·Î ´Ù¸¥ Äھ¼­ Á¢±ÙÇÒ ¼ö ÀÖ´Â ¿µ¿ªÀ̸é ij½¬¶óÀÎ ´ÜÀ§·Î ¶³¾îÁú ¼ö ÀÖ°Ô ÀûÀýÈ÷ ÆÐµùÇÒ °Í
  • ³í¸®ÀûÀ¸·Î °°ÀÌ »ç¿ëµÇ´Â µ¥ÀÌÅͶóµµ, ¼º´ÉÀ» À§Çؼ­ ¼­·Î ¶³¾îÆ®¸®´Â °ÍÀ» °í·ÁÇÒ °Í.

Å×½ºÆ® ÄÚµå : pthread·Î ¹Ù²ã¼­ Å×½ºÆ®ÇغÁ¾ß °Ú´Ù.
#include <windows.H> 
#include <stdio.H> 
#include <tchar.H> 
  
volatile int data1; 
volatile int data2; 
  
DWORD CALLBACK TestThread1(void* /*arg*/) 
{ 
    for (int i = 0; i < 500000000; ++i) 
        data1 = data1 + 1; 
    return data1; 
} 
  
DWORD CALLBACK TestThread2(void* /*arg*/) 
{ 
    for (int i = 0; i < 500000000; ++i) 
        data2 = data2 + 1; 
    return data2; 
} 
  
int _tmain(int argc, _TCHAR* argv[]) 
{ 
    HANDLE thread[2]; 
    SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); 
  
    DWORD startTime = GetTickCount(); 
    thread[0] = CreateThread(NULL, 0, TestThread1, (LPVOID)0, 0, NULL); 
    thread[1] = CreateThread(NULL, 0, TestThread2, (LPVOID)0, 0, NULL); 
    WaitForMultipleObjects(2, thread, TRUE, INFINITE); 
    _tprintf(_T("%d\n"), GetTickCount() - startTime); 
    return 0; 
} 
 

º´·Ä ÇÁ·Î±×·¡¹Ö °ü·Ã Âü°í ³»¿ë

category_C
category__1
EmailÀ» ±âÀÔÇϸé, ´ñ±ÛÀÌ ¸ÞÀÏ·Î Àü´ÞµË´Ï´Ù.