· KLDP.org · KLDP.net · KLDP Wiki · KLDP BBS ·
Linuxdoc Sgml/Thread_Programming-TRANS

Linux Threads Programming

Linux Threads Programming

Matteo Dell'Omodarme matt@martine2.difi.unipi.it ÁöÀ½ ÀÓÁ¾±Õ hermes44@secsm.org ¿Å±è 1999³â 12¿ù 7ÀÏ

1. ¾à°£ÀÇ ÀÌ·Ð

1.1 ¼Ò°³

LinuxThreads´Â ´ÙÁß ¾²·¹µå ÇÁ·Î±×·¡¹ÖÀ» À§ÇÑ ¸®´ª½º ¶óÀ̺귯¸®ÀÌ´Ù. LinuxThreads´Â Ä¿³Î ¼öÁØÀÇ ¾²·¹µå¸¦ Á¦°øÇÑ´Ù; ¾²·¹µåµéÀº clone() ½Ã½ºÅÛÄÝ¿¡ ÀÇÇØ ¸¸µé¾îÁö°í ¸ðµç ½ºÄÉÁÙ¸µÀº Ä¿³Î¿¡¼­ ÀÌ·ç¾îÁø´Ù. Posix 1003.1c API¸¦ ±¸ÇöÇÏ¿´°í Ä¿³Î 2.0.0ÀÌ»óÀÇ Ä¿³Î°ú ÀûÀýÇÑ C ¶óÀ̺귯¸®¸¦ °¡Áö°í ÀÖ´Â ¾î¶°ÇÑ ¸®´ª½º ½Ã½ºÅÛ¿¡ µ¿ÀÛÇÑ´Ù.

1.2 ¾²·¹µå¶õ ¹«¾ùÀΰ¡?

¾²·¹µå´Â ÇÁ·Î±×·¥À» ÅëÇÑ Á¦¾îÀÇ ¼øÂ÷ÀûÀÎ È帧ÀÌ´Ù. ±×·¡¼­ ´ÙÁß ¾²·¹µå ÇÁ·Î±×·¡¹ÖÀº ¿©·¯ Á¦¾î ¾²·¹µå°¡ ÇÑ ÇÁ·Î±×·¥¿¡¼­ µ¿½Ã¿¡ ¼öÇàÇÏ´Â º´·Ä ÇÁ·Î±×·¡¹ÖÀÇ ÇÑ ÇüÅÂÀÌ´Ù.

´ÙÁß ¾²·¹µå ÇÁ·Î±×·¡¹ÖÀº ¸ðµç ¾²·¹µå°¡ °°Àº ¸Þ¸ð¸® °ø°£À» (±×¸®°í ÆÄÀÏ µð½ºÅ©¸³ÅÍ¿Í °°Àº ÀϺΠ½Ã½ºÅÛ ÀÚ¿øµéÀ») °øÀ¯ÇÏ´Â À¯´Ð½º ½ºÅ¸ÀÏÀÇ ´ÙÁß ÇÁ·Î¼¼½Ì°ú´Â ´Ù¸£´Ù. ´ë½Å¿¡ À¯´Ð½ºÀÇ ÇÁ·Î¼¼½º¿Í °°ÀÌ ÀڽŸ¸ÀÇ °íÀ¯ ¸Þ¸ð¸®»ó¿¡ µ¿ÀÛÇÑ´Ù. ±×·¡¼­ ÇÑ ÇÁ·Î¼¼½ºÀÇ µÎ ¾²·¹µå »çÀÌÀÇ ¹®¸Æ ±³È¯(context switch)´Â µÎ ÇÁ·Î¼¼½º »çÀÌÀÇ ¹®¸Æ ±³È¯º¸´Ù ±²ÀåÇÑ ¼ö¿ù ÇÏ´Ù.

¾²·¹µå¸¦ »ç¿ëÇÏ´Â µÎ °¡Áö ÁÖ¿äÇÑ ÀÌÀ¯°¡ ÀÖ´Ù:

  • ¾î¶² ÇÁ·Î±×·¥µéÀº ÇϳªÀÇ Á¦¾î È帧 º¸´Ù´Â ¼­·Î Åë½ÅÇÏ´Â ¿©·¯ ¾²·¹µå·Î ÀÛ¼ºµÉ ¶§¸¸ ÃÖ°íÀÇ ¼º´ÉÀ» ³¾ ¼ö ÀÖ´Ù. (Áï, ¼­¹öµé)
  • ´ÙÁß ÇÁ·Î¼¼¼­ ½Ã½ºÅÛ¿¡¼­, ¾²·¹µåµéÀº ¿©·¯ ÇÁ·Î¼¼¼­»ó¿¡¼­ º´·ÄÀû À¸·Î ¼öÇàµÉ ¼ö ÀÖ´Ù. ÀÌ´Â ÇÑ ÇÁ·Î±×·¥ÀÌ ´Ù¸¥ ÇÁ·Î¼¼¼­¿¡ ÀÛ¾÷À» ºÐ¹èÇÒ ¼ö ÀÖ°Ô ÇØÁØ´Ù. ÀÌ·± ÇÁ·Î±×·¥Àº ÇÑ ¹ø¿¡ ÇÑ CPU¸¸À» »ç¿ëÇÒ ¼ö ÀÖ´Â ´ÜÀÏ ¾²·¹µå ÇÁ·Î±×·¥ º¸´Ù ÈξÀ ´õ ºü¸£´Ù.

1.3 ¿øÀÚ¼º(atomicity)°ú Èֹ߼º(volatility)

¾²·¹µå¿¡ ÀÇÇØ °øÀ¯µÇ´Â ¸Þ¸ð¸®¸¦ Á¢±ÙÇÏ´Â µ¥´Â ´õ ÁÖÀÇ°¡ ÇÊ¿äÇÏ´Ù. º´·Ä ÇÁ·Î±×·¥Àº ÀϹÝÀûÀÎ Áö¿ª ¸Þ¸ð¸®Ã³·³ °øÀ¯ ¸Þ¸ð¸® °´Ã¼¸¦ Á¢±ÙÇÒ ¼ö ¾ø±â ¶§¹®ÀÌ´Ù.

¿øÀÚ¼º(atomicity)´Â ¾î¶² °´Ã¼¿¡ ´ëÇÑ ¿¬»êÀº ºÐ¸®µÉ ¼ö ¾ø´Â, ÀÎÅÍ·´Æ® µÇ´Â ¾Ê´Â °úÁ¤À¸·Î ÀÌ·ç¾îÁ®¾ß µÇ´Ù´Â °³³äÀ» ¸»ÇÑ´Ù. °øÀ¯ ¸Þ¸ð¸®»óÀÇ µ¥ÀÌÅÍ¿¡ ´ëÇÑ ¿¬»êÀº ¿øÀÚÀûÀ¸·Î ÀÌ·ç¾îÁú ¼ö ¾ø´Ù. °Ô´Ù°¡ GCC ÄÄÆÄÀÏ·¯ ´Â Á¾Á¾ ·¹Áö½ºÅÍ¿¡ °øÀ¯ º¯¼öµéÀÇ °ªÀ» ¹öÆÛ¸µÇÏ´Â ÃÖÀûÈ­¸¦ ¼öÇàÇÒ °Í ÀÌ´Ù. ÀÌ·¸°Ô ¸Þ¸ð¸® ¿¬»êÀ» ÇÇÇÏ´Â °ÍÀÌ¶óµµ ¸ðµç ÇÁ·Î¼¼¼­°¡ °øÀ¯ µ¥ÀÌÅÍÀÇ °ªÀÌ º¯°æµÈ °ÍÀº ¾Ë ¼ö ÀÖ¾î¾ß¸¸ ÇÑ´Ù.

·¹Áö½ºÅÍ¿¡ °øÀ¯ ¸Þ¸ð¸®ÀÇ °ªÀ» ¹öÆÛ¸µÇÏ´Â GCCÀÇ ÃÖÀûÈ­¸¦ ¸·±â À§ÇØ °øÀ¯ ¸Þ¸ð¸® »óÀÇ ¸ðµç °´Ã¼´Â volatile ¼Ó¼ºÀÇ Å¸ÀÔÀ¸·Î ¼±¾ðµÇ¾î¾ß ÇÑ´Ù. ´Ü ÇÑ wordÀÇ volatile °´Ã¼¸¦ ÀÐ°í ¾µ´Â °ÍÀº ¿øÀÚÀûÀ¸·Î ÀÌ·ç¾î Áö±â ¶§¹®ÀÌ´Ù.

1.4 Lock (Àá±Ý)

°á°ú°ªÀ» Àоî¿À±â ÀúÀåÇÏ´Â °ÍÀº µ¶¸³µÈ ¸Þ¸ð¸® ¿¬»êÀÌ´Ù: ++iÀº Ç×»ó °øÀ¯ ¸Þ¸ð¸® »óÀÇ iÀ» 1¸¸Å­ Áõ°¡½ÃÅ°Áö´Â ¾Ê´Â´Ù. µÎ ¿¬»ê »çÀÌ¿¡ ´Ù¸¥ ÇÁ·Î¼¼¼­°¡ iÀ» Á¢±ÙÇÒ ¼ö Àֱ⠶§¹®ÀÌ´Ù. ±×·¡¼­ µÎ ÇÁ·Î¼¼½º°¡ µÑ ´Ù ++iÀ» ¼öÇàÇÑ´Ù¸é 2°¡ ¾Æ´Ñ 1¸¸À» Áõ°¡µÉ ¼öµµ ÀÖ´Ù.

±×·¡¼­ ÇÑ ¾²·¹µå°¡ º¯¼öÀÇ °ªÀ» ¹Ù²Ù´Â µ¿¾ÈÀº ´Ù¸¥ ¾²·¹µå°¡ ±× º¯¼ö¿¡ ´ëÇÑ ÀÛ¾÷À» ÇÒ ¼ö ¾ø°Ô ÇÏ´Â ½Ã½ºÅÛ ÄÝÀÌ ÇÊ¿äÇÏ´Ù. ÀÌ´Â ¾Æ·¡ ¼³¸íÇÑ lock ¹æ¹ýÀ¸·Î ±¸ÇöµÈ´Ù. °øÀ¯ º¯¼öÀÇ °ªÀ» ¹Ù²Ù´Â ·çƾÀ» ¼öÇàÇÏ´Â µÎ ¾²·¹µå°¡ ÀÖ´Ù°í °¡Á¤À» ÇÏÀÚ. ±× ·çƾÀÌ Á¤È®ÇÑ °á°ú¸¦ ¾ò±â À§Çؼ­´Â ´ÙÀ½°ú °°ÀÌ ÇØ¾ß ÇÑ´Ù.

  • i º¯¼ö¿¡ ´ëÇØ lockÀ» °Ç´Ù.
  • Àá±ä º¯¼öÀÇ °ªÀ» ¼öÁ¤ÇÑ´Ù.
  • lockÀ» Á¦°ÅÇÑ´Ù.

ÇÑ º¯¼ö¿¡ ´ëÇÑ lockÀÌ °É¸± ¶§ ±× lockÀ» °Ç ¾²·¹µå¸¸ÀÌ ±× °ªÀ» ¹Ù²Ü ¼ö ÀÖ´Ù. Àá±Ù ¶§¹®¿¡ ´Ù¸¥ ¾²·¹µåµéÀº ºí·°ÀÌ µÉ °ÍÀÌ´Ù. ÇÑ º¯¼ö¿¡ ´ëÇؼ­ ´Â ÇÑ ¹ø¿¡ ÇϳªÀÇ lock¸¸ÀÌ Çã¿ëµÇ±â ¶§¹®ÀÌ´Ù. ¤½Ã¹¹ø° ¾²·¹µå°¡ lock À» Á¦°ÅÇÒ ¶§¸¸ µÎ¹ø° ¾²·¹µå°¡ lockÀ» °É ¼ö ÀÖ´Ù. ±× °á°ú °øÀ¯ º¯¼ö¸¦ ÀÌ¿ëÇÏ´Â °ÍÀº ´Ù¸¥ ÇÁ·Î¼¼¼­µéÀÇ È°µ¿À» ´À¸®°Ô ÇÒ Áöµµ ¸ðµç´Ù. ÇÏÁö¸¸ ÀϹÝÀûÀÎ ÂüÁ¶´Â Áö¿ª ij½Ã¸¦ ÀÌ¿ëÇÑ´Ù.

2. ±×¸®°í ¾à°£ÀÇ ½ÇÁ¦

2.1 pthread.h Çì´õ

LinuxThreads°¡ Á¦°øÇÏ´Â °ÍÀº ¾²·¹µå ·çƾµéÀÇ ÇÁ·ÎÅäŸÀÔÀ» ¼±¾ðÇÏ´Â /usr/include/pthread.h Çì´õ¸¦ ÅëÇؼ­ ÀÌ¿ë °¡´ÉÇÏ´Ù.

´ÙÁß ¾²·¹µå ÇÁ·Î±×·¥ÀÇ ÀÛ¼ºÀº ±âº»ÀûÀ¸·Î µÎ ´Ü°èÀÇ °úÁ¤ÀÌ´Ù:

  • °øÀ¯ º¯¼öµé¿¡ lockÀ» °É°í ¾²·¹µå¸¦ ¸¸µé±â À§ÇÑ pthread ·çƾµéÀ» »ç¿ëÇÑ´Ù.
  • ¾²·¹µå ¼­ºê ·çƾ¿¡ ³Ñ°Ü¾ß ÇÒ ¸ð¸¥ ÀÎÀÚµéÀ» Æ÷ÇÔÇÏ´Â ±¸Á¶Ã¼¸¦ ¸¸µç´Ù.

¸î °¡Áö ±âº»ÀûÀÎ pthread.hÀÇ ·çƾµéÀ» °£´ÜÈ÷ ¼³¸íÇϸ鼭 ÀÌ µÎ ´Ü°è¸¦ ½ÇÆ캸ÀÚ.

2.2 lockÀÇ ÃʱâÈ­

Çؾ߸¸ Çϴ ù¹ø° Çൿµé ÁßÀÇ Çϳª´Â ¸ðµç lockµéÀ» ÃʱâÈ­ÇÏ´Â °ÍÀÌ´Ù. POSIX lockµéÀº pthread_mutex_t ŸÀÔÀÇ º¯¼ö·Î ¼±¾ðµÈ´Ù; °¢ lockÀ» ÃʱâÈ­Çϱâ À§Çã ´ÙÀ½ ·çƾÀ» È£ÃâÇÒ ÇÊ¿ä°¡ ÀÖ´Ù:

int pthread_mutex_init(pthread_mutex_t *mutex, const pthread
_mutexattr_t *mutexattr);

¹­¾î¼­ º¸¸é:

#include <pthread.h>
...
        pthread_mutex_t lock;
        pthread_mutex_init(&lock, NULL);
...

pthread_mutex_init ÇÔ¼ö´Â mutex ÀÎÀÚ°¡ °¡1¸£Å°´Â mutex °´Ã¼¸¦ mutexattr¿¡ ÀÇÇØ ¸í½ÃµÈ mutex ¼Ó¼º¿¡ µû¶ó ÃʱâÈ­¸¦ ÇÑ´Ù. mutexattrÀÇ NULLÀ̸é, µðÆúÆ® ¼Ó¼ºÀÌ »ç¿ëµÈ´Ù.

°è¼ÓÇì¼­ ÀÌ ÃʱâÈ­µÈ lockµéÀ» ¾î¶»°Ô »ç¿ëÇÏ´ÂÁö º¸°Ú´Ù.

2.3 ¾²·¹µå »ý¼ºÇϱâ

POSIX´Â °¢ ¾²·¹µå¸¦ ³ªÅ¸³»±â À§ÇØ »ç¿ëÀÚ°¡ pthread_t ŸÀÔÀÇ º¯¼ö¸¦ ¼±¾ðÇϵµ·Ï ÇÑ´Ù. ´ÙÀ½ È£Ãâ·Î ¾²·¹µå°¡ »ý¼ºµÈ´Ù:

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

¼º°øÇÑ´Ù¸é »õ·ÎÀÌ »ý¼ºµÈ ¾²·¹µåÀÇ id°¡ thread ÀÎÀÚ°¡ Áö½ÃÇÑ ¿µ¿ª¿¡ Á¤ÀåÀÌ µÇ°í 0ÀÎ ¸®ÅϵȴÙ. ¿¡·¯°¡ ¹ß»ýÇϸé 0ÀÌ ¾Æ´Ñ °ªÀÌ ¸®ÅϵȴÙ.

f() ·çƾÀ» ¼öÇàÇÏ´Â ¾²·¹µå¸¦ ¸¸µé°í f()¿¡ arg º¯¼ö¸¦ °¡¸£Å°´Â Æ÷ÀÌÅÍ ¸¦ ³Ñ±â±â À§Çؼ­´Â ´ÙÀ½°ú °°ÀÌ ÇÑ´Ù:

#include <pthread.h>
...
        pthread_t thread;
        pthread_create(&thread, NULL, f, &arg).
...

f() ·çºóÀº ´ÙÀ½°ú °°Àº ÇÁ·ÎÅäŸÀÔÀ» °¡Á®¾ß ÇÑ´Ù:

void *f(void *arg);

2.4 ±ú²ýÇÑ Á¾·á

¸¶Áö¸· ´Ü°è·Î f() ·çƾÀÇ °á°ú¸¦ Á¢±ÙÇϱâ Àü¿¡ ¸¸µç ¸ðµç ¾²·¹µå°¡ Á¾·á ÇÒ ¶§±îÁö ±â´Ù·Á¾ß ÇÑ´Ù. ´ÙÀ½À» È£ÃâÇÑ´Ù:

int pthread_join(pthread_t th, void **thread_return);

th°¡ °¡¸£Å°´Â ¾²·¹µå°¡ Á¾·áÇÒ ¶§±îÁö À§ÀÇ ÇÔ¼ö¸¦ È£ÃâÇÑ ¾²·¹µåÀÇ ¼öÇà À» ¸ØÃá´Ù. ¸¸¾à thread_returnÀÌ NULLÀ̴ϸé thÀÇ ¸®ÅÏ°ªÀº thread_returnÀÌ °¡¸®Å° ´Â ¿µ¿ª¿¡ ÀúÀåµÈ´Ù.

2.5 ¾²·¹µå ·çƾ¿¡ µ¥ÀÌÅÍ Àü´ÞÇϱâ

È£ÃâÇÑ ·çƾÀÇ Á¤º¸¸¦ ¾²·¹µå ·çƾ¿¡ ³Ñ±â´Â µÎ °¡Áö ¹æ¹ýÀÌ ÀÖ´Ù:

  • Àü¿ª º¯¼ö
  • ±¸Á¶Ã¼

µÎ¹ø° °ÍÀÌ ÄÚµåÀÇ ¸ðµâ¼ºÀ» º¸ÀüÇÏ´Â µ¥ °¡Àå ÁÁÀº ¼±ÅÃÀÌ´Ù. ±¸Á¦Ã¼´Â ¼¼ °¡Áö ´Ü°èÀÇ Á¤º¸¸¦ Æ÷ÇÔÇØ¾ß ÇÑ´Ù; ù°·Î °øÀ¯ º¯¼öµé°ú lockµé¿¡ °üÇÑ Á¤º¸, µÎ¹ø°·Î ·çƾ¿¡¼­ ÇÊ¿ä·Î ÇÏ´Â ¸ðµç µ¥ÀÌÅÍ¿¡ ´ëÇÑ Á¤º¸, ¼¼¹ø°·Î ¾²·¡µé¸¦ ±¸ºÐÇØÁÖ´Â id¿Í ¾²·¹µå°¡ ÀÌ¿ëÇÒ ¼ö ÀÖ´Â CPUÀÇ ¼ö¿¡ ´ëÇÑ Á¤º¸ (·±Å¸ÀÓ¿¡ ÀÌ Á¤º¸¸¦ Á¦°øÇÏ´Â °ÍÀÌ ´õ ½±´Ù). ±¸Á¶Ã¼ÀÇ Ã¹¹ø° ¿ä¼ÒÀ» »ìÆ캸ÀÚ; ³Ñ°ÜÁø Á¤º¸´Â ¸ðµç ¾²·¹µåµé »çÀÌÀÇ °øÀ¯µµ´Í °ÍÀÌ ¾î¾ßÇÑ´Ù. ±×·¡¼­ ÇÊ¿äÇÑ º¯¼öµé°ú lockµéÀÇ Æ÷ÀÎÅ͸¦ »ç¿ë ÇØ¾ß ÇÑ´Ù. double ŸÀÔÀÇ °øÀ¯ º¯¼ö var¿Í ±× ¿¡ ´ëÇÑ lockÀ» ³Ñ±â±â À§ÇØ ±¸Á¶Ã¼´Â µÎ ¸â¹ö º¯¼ö¸¦ °¡Á®¾ß¸¸ ÇÑ´Ù:

double volatile *var;
pthread_mutex_t *var_lock;

volatile ¼Ó¼ºÀÇ »ç¿ë À§Ä¡¿¡ ÁÖ¸ñÇ϶ó. ÀÌ´Â Æ÷ÀÎÅÍ ÀÚü°¡ ¾Æ´Ï¶ó var°¡ volatileÀÓÀ» ³ªÅ¸³½´Ù.

2.6 º´·Ä ÄÚµåÀÇ ¿¹

¾²·¡µé¸¦ ÀÌ¿ëÇÏ¿© ½±°Ô º´·ÄÈ­¸¦ ÇÒ ¼ö ÀÖ´Â ÇÁ·Î±×·¥ÀÇ ¿¹´Â µÎ º¤ÅÍÀÇ ½ºÄ®¶óÄÚ°öÀ» °è»êÀÌ´Ù. ÁÖ¼®À» ºÙÀÎ Äڵ带 Á¦½ÃÇÑ´Ù.

/* ÄÄÆÄÀÏ ÇÏ·Á¸é gcc  -D_REENTRANT -lpthread */

#include <stdio.h>
#include <pthread.h>

/* ¾Ë¸ÂÀº ±¸Á¶Ã¼ ¼±¾ð */ 
typedef struct {
        double volatile *p_s;      /* ½ºÄ®¶ó °öÀÇ °øÀ¯ º¯¼ö */
        pthread_mutex_t *p_s_lock; /* º¯¼ö sÀÇ lock */
        int n;                     /* ¾²·¹µåÀÇ ¼ö */
        int nproc;                 /* ÀÌ¿ëÇÒ ¼ö ÀÖ´Â ÇÁ·Î¼¼¼­ÀÇ ¼ö */
        double *x;                 /* ù¹ø° º¤ÅÍÀÇ µ¥ÀÌÅÍ */
        double *y;                 /* µÎ¹ø° º¤ÅÍÀÇ µ¥ÀÌÅÍ */
        int l;                     /* º¤ÅÍÀÇ ±æÀÌ */
} DATA;

void *SMP_scalprod(void *arg)
{
        register double localsum;
        long i;
        DATA D = *(DATA *)arg;

        localsum = 0.0;

        /* °¢ ¾²·¹µå´Â i = D.n¿¡¼­ ºÎÅÍ ½ºÄ®¶ó °öÀ» ½ÃÀÛÇÑ´Ù. 
           D.n = 1, 2, ...
           D.nproc °ªÀ» °®´Â´Ù. Á¤È®È÷ D.nproc°³ÀÇ ¾²·¹µå°¡ ÀÖ±â 
           ¶§¹®¿¡ iÀÇ Áõ°¡ °°Àº D.nprocÀÌ´Ù. */

        for(i = D.n; i < D.l; i += D.nproc)
        localsum += D.x[i]*D.y[i];

        /* s¿¡ ´ëÇÑ lockÀ» °Ç´Ù ... */
        pthread_mutex_lock(D.p_s_lock);

        /* ... sÀÇ °ªÀ» ¹Ù²Û´Ù. ... */
        *(D.p_s) += localsum;

        /* ... ±×¸®°í lock¸¦ Á¦°ÅÇÑ´Ù. */
        pthread_mutex_unlock(D.p_s_lock);

        return NULL;
}

#define L 9     /* º¤ÅÍÀÇ Â÷¿ø */

int main(int argc, char **argv)
{
        pthread_t *thread;
        void *retval;
        int cpu, i;
        DATA *A;
        volatile double s = 0; /* °øÀ¯ º¯¼ö */ 
        pthread_mutex_t s_lock; 
        double x[L], y[L];

        if (argc != 2) {
                printf("usage: %s <number of CPU>\n", argv[0]);
                exit(1);
        }
        
        cpu = atoi(argv[1]);
        thread = (pthread_t *) calloc(cpu, sizeof(pthread_t));
        A = (DATA *) calloc(cpu, sizeof(DATA));

 
        for (i = 0; i < L; i++)
        x[i] = y[i] = i;

        /* lock º¯¼ö¸¦ ÃʱâÈ­ÇÑ´Ù. */
        pthread_mutex_init(&s_lock, NULL);

        for (i = 0; i < cpu; i++) {
                /* ±¸Á¶Ã¼¸¦ ÃʱâÈ­ÇÑ´Ù. */
                A[i].n = i; /* ¾²·¹µåÀÇ ¼ö */
                A[i].x = x;
                A[i].y = y;
                A[i].l = L;
                A[i].nproc = cpu; /* CPUÀÇ ¼ö */
                A[i].p_s = &s;
                A[i].p_s_lock = &s_lock;

                if (pthread_create(&thread[i], NULL, SMP_scalprod, 
                    &A[i])) {
                        fprintf(stderr, "%s: cannot make thread\n", 
                                argv[0]);
                        exit(1);
                }
        }

        for (i = 0; i < cpu; i++) {
                if (pthread_join(thread[i], &retval)) {
                        fprintf(stderr, "%s: cannot join thread\n", 
                                argv[0]);
                        exit(1);
                }
        }

        printf("s = %f\n", s);
        exit(0);
}

Copyright ¨Ï 1999, Matteo Dell'Omodarme

Published in Issue 48 of Linux Gazette, December 1999

Linux Threads Programming

Linux Threads Programming

Matteo Dell'Omodarme matt@martine2.difi.unipi.it ÁöÀ½ ÀÓÁ¾±Õ hermes44@secsm.org ¿Å±è 1999³â 12¿ù 7ÀÏ

1. ¾à°£ÀÇ ÀÌ·Ð

1.1 ¼Ò°³

LinuxThreads´Â ´ÙÁß ¾²·¹µå ÇÁ·Î±×·¡¹ÖÀ» À§ÇÑ ¸®´ª½º ¶óÀ̺귯¸®ÀÌ´Ù. LinuxThreads´Â Ä¿³Î ¼öÁØÀÇ ¾²·¹µå¸¦ Á¦°øÇÑ´Ù; ¾²·¹µåµéÀº clone() ½Ã½ºÅÛÄÝ¿¡ ÀÇÇØ ¸¸µé¾îÁö°í ¸ðµç ½ºÄÉÁÙ¸µÀº Ä¿³Î¿¡¼­ ÀÌ·ç¾îÁø´Ù. Posix 1003.1c API¸¦ ±¸ÇöÇÏ¿´°í Ä¿³Î 2.0.0ÀÌ»óÀÇ Ä¿³Î°ú ÀûÀýÇÑ C ¶óÀ̺귯¸®¸¦ °¡Áö°í ÀÖ´Â ¾î¶°ÇÑ ¸®´ª½º ½Ã½ºÅÛ¿¡ µ¿ÀÛÇÑ´Ù.

1.2 ¾²·¹µå¶õ ¹«¾ùÀΰ¡?

¾²·¹µå´Â ÇÁ·Î±×·¥À» ÅëÇÑ Á¦¾îÀÇ ¼øÂ÷ÀûÀÎ È帧ÀÌ´Ù. ±×·¡¼­ ´ÙÁß ¾²·¹µå ÇÁ·Î±×·¡¹ÖÀº ¿©·¯ Á¦¾î ¾²·¹µå°¡ ÇÑ ÇÁ·Î±×·¥¿¡¼­ µ¿½Ã¿¡ ¼öÇàÇÏ´Â º´·Ä ÇÁ·Î±×·¡¹ÖÀÇ ÇÑ ÇüÅÂÀÌ´Ù.

´ÙÁß ¾²·¹µå ÇÁ·Î±×·¡¹ÖÀº ¸ðµç ¾²·¹µå°¡ °°Àº ¸Þ¸ð¸® °ø°£À» (±×¸®°í ÆÄÀÏ µð½ºÅ©¸³ÅÍ¿Í °°Àº ÀϺΠ½Ã½ºÅÛ ÀÚ¿øµéÀ») °øÀ¯ÇÏ´Â À¯´Ð½º ½ºÅ¸ÀÏÀÇ ´ÙÁß ÇÁ·Î¼¼½Ì°ú´Â ´Ù¸£´Ù. ´ë½Å¿¡ À¯´Ð½ºÀÇ ÇÁ·Î¼¼½º¿Í °°ÀÌ ÀڽŸ¸ÀÇ °íÀ¯ ¸Þ¸ð¸®»ó¿¡ µ¿ÀÛÇÑ´Ù. ±×·¡¼­ ÇÑ ÇÁ·Î¼¼½ºÀÇ µÎ ¾²·¹µå »çÀÌÀÇ ¹®¸Æ ±³È¯(context switch)´Â µÎ ÇÁ·Î¼¼½º »çÀÌÀÇ ¹®¸Æ ±³È¯º¸´Ù ±²ÀåÇÑ ¼ö¿ù ÇÏ´Ù.

¾²·¹µå¸¦ »ç¿ëÇÏ´Â µÎ °¡Áö ÁÖ¿äÇÑ ÀÌÀ¯°¡ ÀÖ´Ù:

  • ¾î¶² ÇÁ·Î±×·¥µéÀº ÇϳªÀÇ Á¦¾î È帧 º¸´Ù´Â ¼­·Î Åë½ÅÇÏ´Â ¿©·¯ ¾²·¹µå·Î ÀÛ¼ºµÉ ¶§¸¸ ÃÖ°íÀÇ ¼º´ÉÀ» ³¾ ¼ö ÀÖ´Ù. (Áï, ¼­¹öµé)
  • ´ÙÁß ÇÁ·Î¼¼¼­ ½Ã½ºÅÛ¿¡¼­, ¾²·¹µåµéÀº ¿©·¯ ÇÁ·Î¼¼¼­»ó¿¡¼­ º´·ÄÀû À¸·Î ¼öÇàµÉ ¼ö ÀÖ´Ù. ÀÌ´Â ÇÑ ÇÁ·Î±×·¥ÀÌ ´Ù¸¥ ÇÁ·Î¼¼¼­¿¡ ÀÛ¾÷À» ºÐ¹èÇÒ ¼ö ÀÖ°Ô ÇØÁØ´Ù. ÀÌ·± ÇÁ·Î±×·¥Àº ÇÑ ¹ø¿¡ ÇÑ CPU¸¸À» »ç¿ëÇÒ ¼ö ÀÖ´Â ´ÜÀÏ ¾²·¹µå ÇÁ·Î±×·¥ º¸´Ù ÈξÀ ´õ ºü¸£´Ù.

1.3 ¿øÀÚ¼º(atomicity)°ú Èֹ߼º(volatility)

¾²·¹µå¿¡ ÀÇÇØ °øÀ¯µÇ´Â ¸Þ¸ð¸®¸¦ Á¢±ÙÇÏ´Â µ¥´Â ´õ ÁÖÀÇ°¡ ÇÊ¿äÇÏ´Ù. º´·Ä ÇÁ·Î±×·¥Àº ÀϹÝÀûÀÎ Áö¿ª ¸Þ¸ð¸®Ã³·³ °øÀ¯ ¸Þ¸ð¸® °´Ã¼¸¦ Á¢±ÙÇÒ ¼ö ¾ø±â ¶§¹®ÀÌ´Ù.

¿øÀÚ¼º(atomicity)´Â ¾î¶² °´Ã¼¿¡ ´ëÇÑ ¿¬»êÀº ºÐ¸®µÉ ¼ö ¾ø´Â, ÀÎÅÍ·´Æ® µÇ´Â ¾Ê´Â °úÁ¤À¸·Î ÀÌ·ç¾îÁ®¾ß µÇ´Ù´Â °³³äÀ» ¸»ÇÑ´Ù. °øÀ¯ ¸Þ¸ð¸®»óÀÇ µ¥ÀÌÅÍ¿¡ ´ëÇÑ ¿¬»êÀº ¿øÀÚÀûÀ¸·Î ÀÌ·ç¾îÁú ¼ö ¾ø´Ù. °Ô´Ù°¡ GCC ÄÄÆÄÀÏ·¯ ´Â Á¾Á¾ ·¹Áö½ºÅÍ¿¡ °øÀ¯ º¯¼öµéÀÇ °ªÀ» ¹öÆÛ¸µÇÏ´Â ÃÖÀûÈ­¸¦ ¼öÇàÇÒ °Í ÀÌ´Ù. ÀÌ·¸°Ô ¸Þ¸ð¸® ¿¬»êÀ» ÇÇÇÏ´Â °ÍÀÌ¶óµµ ¸ðµç ÇÁ·Î¼¼¼­°¡ °øÀ¯ µ¥ÀÌÅÍÀÇ °ªÀÌ º¯°æµÈ °ÍÀº ¾Ë ¼ö ÀÖ¾î¾ß¸¸ ÇÑ´Ù.

·¹Áö½ºÅÍ¿¡ °øÀ¯ ¸Þ¸ð¸®ÀÇ °ªÀ» ¹öÆÛ¸µÇÏ´Â GCCÀÇ ÃÖÀûÈ­¸¦ ¸·±â À§ÇØ °øÀ¯ ¸Þ¸ð¸® »óÀÇ ¸ðµç °´Ã¼´Â volatile ¼Ó¼ºÀÇ Å¸ÀÔÀ¸·Î ¼±¾ðµÇ¾î¾ß ÇÑ´Ù. ´Ü ÇÑ wordÀÇ volatile °´Ã¼¸¦ ÀÐ°í ¾µ´Â °ÍÀº ¿øÀÚÀûÀ¸·Î ÀÌ·ç¾î Áö±â ¶§¹®ÀÌ´Ù.

1.4 Lock (Àá±Ý)

°á°ú°ªÀ» Àоî¿À±â ÀúÀåÇÏ´Â °ÍÀº µ¶¸³µÈ ¸Þ¸ð¸® ¿¬»êÀÌ´Ù: ++iÀº Ç×»ó °øÀ¯ ¸Þ¸ð¸® »óÀÇ iÀ» 1¸¸Å­ Áõ°¡½ÃÅ°Áö´Â ¾Ê´Â´Ù. µÎ ¿¬»ê »çÀÌ¿¡ ´Ù¸¥ ÇÁ·Î¼¼¼­°¡ iÀ» Á¢±ÙÇÒ ¼ö Àֱ⠶§¹®ÀÌ´Ù. ±×·¡¼­ µÎ ÇÁ·Î¼¼½º°¡ µÑ ´Ù ++iÀ» ¼öÇàÇÑ´Ù¸é 2°¡ ¾Æ´Ñ 1¸¸À» Áõ°¡µÉ ¼öµµ ÀÖ´Ù.

±×·¡¼­ ÇÑ ¾²·¹µå°¡ º¯¼öÀÇ °ªÀ» ¹Ù²Ù´Â µ¿¾ÈÀº ´Ù¸¥ ¾²·¹µå°¡ ±× º¯¼ö¿¡ ´ëÇÑ ÀÛ¾÷À» ÇÒ ¼ö ¾ø°Ô ÇÏ´Â ½Ã½ºÅÛ ÄÝÀÌ ÇÊ¿äÇÏ´Ù. ÀÌ´Â ¾Æ·¡ ¼³¸íÇÑ lock ¹æ¹ýÀ¸·Î ±¸ÇöµÈ´Ù. °øÀ¯ º¯¼öÀÇ °ªÀ» ¹Ù²Ù´Â ·çƾÀ» ¼öÇàÇÏ´Â µÎ ¾²·¹µå°¡ ÀÖ´Ù°í °¡Á¤À» ÇÏÀÚ. ±× ·çƾÀÌ Á¤È®ÇÑ °á°ú¸¦ ¾ò±â À§Çؼ­´Â ´ÙÀ½°ú °°ÀÌ ÇØ¾ß ÇÑ´Ù.

  • i º¯¼ö¿¡ ´ëÇØ lockÀ» °Ç´Ù.
  • Àá±ä º¯¼öÀÇ °ªÀ» ¼öÁ¤ÇÑ´Ù.
  • lockÀ» Á¦°ÅÇÑ´Ù.

ÇÑ º¯¼ö¿¡ ´ëÇÑ lockÀÌ °É¸± ¶§ ±× lockÀ» °Ç ¾²·¹µå¸¸ÀÌ ±× °ªÀ» ¹Ù²Ü ¼ö ÀÖ´Ù. Àá±Ù ¶§¹®¿¡ ´Ù¸¥ ¾²·¹µåµéÀº ºí·°ÀÌ µÉ °ÍÀÌ´Ù. ÇÑ º¯¼ö¿¡ ´ëÇؼ­ ´Â ÇÑ ¹ø¿¡ ÇϳªÀÇ lock¸¸ÀÌ Çã¿ëµÇ±â ¶§¹®ÀÌ´Ù. ¤½Ã¹¹ø° ¾²·¹µå°¡ lock À» Á¦°ÅÇÒ ¶§¸¸ µÎ¹ø° ¾²·¹µå°¡ lockÀ» °É ¼ö ÀÖ´Ù. ±× °á°ú °øÀ¯ º¯¼ö¸¦ ÀÌ¿ëÇÏ´Â °ÍÀº ´Ù¸¥ ÇÁ·Î¼¼¼­µéÀÇ È°µ¿À» ´À¸®°Ô ÇÒ Áöµµ ¸ðµç´Ù. ÇÏÁö¸¸ ÀϹÝÀûÀÎ ÂüÁ¶´Â Áö¿ª ij½Ã¸¦ ÀÌ¿ëÇÑ´Ù.

2. ±×¸®°í ¾à°£ÀÇ ½ÇÁ¦

2.1 pthread.h Çì´õ

LinuxThreads°¡ Á¦°øÇÏ´Â °ÍÀº ¾²·¹µå ·çƾµéÀÇ ÇÁ·ÎÅäŸÀÔÀ» ¼±¾ðÇÏ´Â /usr/include/pthread.h Çì´õ¸¦ ÅëÇؼ­ ÀÌ¿ë °¡´ÉÇÏ´Ù.

´ÙÁß ¾²·¹µå ÇÁ·Î±×·¥ÀÇ ÀÛ¼ºÀº ±âº»ÀûÀ¸·Î µÎ ´Ü°èÀÇ °úÁ¤ÀÌ´Ù:

  • °øÀ¯ º¯¼öµé¿¡ lockÀ» °É°í ¾²·¹µå¸¦ ¸¸µé±â À§ÇÑ pthread ·çƾµéÀ» »ç¿ëÇÑ´Ù.
  • ¾²·¹µå ¼­ºê ·çƾ¿¡ ³Ñ°Ü¾ß ÇÒ ¸ð¸¥ ÀÎÀÚµéÀ» Æ÷ÇÔÇÏ´Â ±¸Á¶Ã¼¸¦ ¸¸µç´Ù.

¸î °¡Áö ±âº»ÀûÀÎ pthread.hÀÇ ·çƾµéÀ» °£´ÜÈ÷ ¼³¸íÇϸ鼭 ÀÌ µÎ ´Ü°è¸¦ ½ÇÆ캸ÀÚ.

2.2 lockÀÇ ÃʱâÈ­

Çؾ߸¸ Çϴ ù¹ø° Çൿµé ÁßÀÇ Çϳª´Â ¸ðµç lockµéÀ» ÃʱâÈ­ÇÏ´Â °ÍÀÌ´Ù. POSIX lockµéÀº pthread_mutex_t ŸÀÔÀÇ º¯¼ö·Î ¼±¾ðµÈ´Ù; °¢ lockÀ» ÃʱâÈ­Çϱâ À§Çã ´ÙÀ½ ·çƾÀ» È£ÃâÇÒ ÇÊ¿ä°¡ ÀÖ´Ù:

int pthread_mutex_init(pthread_mutex_t *mutex, const pthread
_mutexattr_t *mutexattr);

¹­¾î¼­ º¸¸é:

#include <pthread.h>
...
        pthread_mutex_t lock;
        pthread_mutex_init(&lock, NULL);
...

pthread_mutex_init ÇÔ¼ö´Â mutex ÀÎÀÚ°¡ °¡1¸£Å°´Â mutex °´Ã¼¸¦ mutexattr¿¡ ÀÇÇØ ¸í½ÃµÈ mutex ¼Ó¼º¿¡ µû¶ó ÃʱâÈ­¸¦ ÇÑ´Ù. mutexattrÀÇ NULLÀ̸é, µðÆúÆ® ¼Ó¼ºÀÌ »ç¿ëµÈ´Ù.

°è¼ÓÇì¼­ ÀÌ ÃʱâÈ­µÈ lockµéÀ» ¾î¶»°Ô »ç¿ëÇÏ´ÂÁö º¸°Ú´Ù.

2.3 ¾²·¹µå »ý¼ºÇϱâ

POSIX´Â °¢ ¾²·¹µå¸¦ ³ªÅ¸³»±â À§ÇØ »ç¿ëÀÚ°¡ pthread_t ŸÀÔÀÇ º¯¼ö¸¦ ¼±¾ðÇϵµ·Ï ÇÑ´Ù. ´ÙÀ½ È£Ãâ·Î ¾²·¹µå°¡ »ý¼ºµÈ´Ù:

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

¼º°øÇÑ´Ù¸é »õ·ÎÀÌ »ý¼ºµÈ ¾²·¹µåÀÇ id°¡ thread ÀÎÀÚ°¡ Áö½ÃÇÑ ¿µ¿ª¿¡ Á¤ÀåÀÌ µÇ°í 0ÀÎ ¸®ÅϵȴÙ. ¿¡·¯°¡ ¹ß»ýÇϸé 0ÀÌ ¾Æ´Ñ °ªÀÌ ¸®ÅϵȴÙ.

f() ·çƾÀ» ¼öÇàÇÏ´Â ¾²·¹µå¸¦ ¸¸µé°í f()¿¡ arg º¯¼ö¸¦ °¡¸£Å°´Â Æ÷ÀÌÅÍ ¸¦ ³Ñ±â±â À§Çؼ­´Â ´ÙÀ½°ú °°ÀÌ ÇÑ´Ù:

#include <pthread.h>
...
        pthread_t thread;
        pthread_create(&thread, NULL, f, &arg).
...

f() ·çºóÀº ´ÙÀ½°ú °°Àº ÇÁ·ÎÅäŸÀÔÀ» °¡Á®¾ß ÇÑ´Ù:

void *f(void *arg);

2.4 ±ú²ýÇÑ Á¾·á

¸¶Áö¸· ´Ü°è·Î f() ·çƾÀÇ °á°ú¸¦ Á¢±ÙÇϱâ Àü¿¡ ¸¸µç ¸ðµç ¾²·¹µå°¡ Á¾·á ÇÒ ¶§±îÁö ±â´Ù·Á¾ß ÇÑ´Ù. ´ÙÀ½À» È£ÃâÇÑ´Ù:

int pthread_join(pthread_t th, void **thread_return);

th°¡ °¡¸£Å°´Â ¾²·¹µå°¡ Á¾·áÇÒ ¶§±îÁö À§ÀÇ ÇÔ¼ö¸¦ È£ÃâÇÑ ¾²·¹µåÀÇ ¼öÇà À» ¸ØÃá´Ù. ¸¸¾à thread_returnÀÌ NULLÀ̴ϸé thÀÇ ¸®ÅÏ°ªÀº thread_returnÀÌ °¡¸®Å° ´Â ¿µ¿ª¿¡ ÀúÀåµÈ´Ù.

2.5 ¾²·¹µå ·çƾ¿¡ µ¥ÀÌÅÍ Àü´ÞÇϱâ

È£ÃâÇÑ ·çƾÀÇ Á¤º¸¸¦ ¾²·¹µå ·çƾ¿¡ ³Ñ±â´Â µÎ °¡Áö ¹æ¹ýÀÌ ÀÖ´Ù:

  • Àü¿ª º¯¼ö
  • ±¸Á¶Ã¼

µÎ¹ø° °ÍÀÌ ÄÚµåÀÇ ¸ðµâ¼ºÀ» º¸ÀüÇÏ´Â µ¥ °¡Àå ÁÁÀº ¼±ÅÃÀÌ´Ù. ±¸Á¦Ã¼´Â ¼¼ °¡Áö ´Ü°èÀÇ Á¤º¸¸¦ Æ÷ÇÔÇØ¾ß ÇÑ´Ù; ù°·Î °øÀ¯ º¯¼öµé°ú lockµé¿¡ °üÇÑ Á¤º¸, µÎ¹ø°·Î ·çƾ¿¡¼­ ÇÊ¿ä·Î ÇÏ´Â ¸ðµç µ¥ÀÌÅÍ¿¡ ´ëÇÑ Á¤º¸, ¼¼¹ø°·Î ¾²·¡µé¸¦ ±¸ºÐÇØÁÖ´Â id¿Í ¾²·¹µå°¡ ÀÌ¿ëÇÒ ¼ö ÀÖ´Â CPUÀÇ ¼ö¿¡ ´ëÇÑ Á¤º¸ (·±Å¸ÀÓ¿¡ ÀÌ Á¤º¸¸¦ Á¦°øÇÏ´Â °ÍÀÌ ´õ ½±´Ù). ±¸Á¶Ã¼ÀÇ Ã¹¹ø° ¿ä¼ÒÀ» »ìÆ캸ÀÚ; ³Ñ°ÜÁø Á¤º¸´Â ¸ðµç ¾²·¹µåµé »çÀÌÀÇ °øÀ¯µµ´Í °ÍÀÌ ¾î¾ßÇÑ´Ù. ±×·¡¼­ ÇÊ¿äÇÑ º¯¼öµé°ú lockµéÀÇ Æ÷ÀÎÅ͸¦ »ç¿ë ÇØ¾ß ÇÑ´Ù. double ŸÀÔÀÇ °øÀ¯ º¯¼ö var¿Í ±× ¿¡ ´ëÇÑ lockÀ» ³Ñ±â±â À§ÇØ ±¸Á¶Ã¼´Â µÎ ¸â¹ö º¯¼ö¸¦ °¡Á®¾ß¸¸ ÇÑ´Ù:

double volatile *var;
pthread_mutex_t *var_lock;

volatile ¼Ó¼ºÀÇ »ç¿ë À§Ä¡¿¡ ÁÖ¸ñÇ϶ó. ÀÌ´Â Æ÷ÀÎÅÍ ÀÚü°¡ ¾Æ´Ï¶ó var°¡ volatileÀÓÀ» ³ªÅ¸³½´Ù.

2.6 º´·Ä ÄÚµåÀÇ ¿¹

¾²·¡µé¸¦ ÀÌ¿ëÇÏ¿© ½±°Ô º´·ÄÈ­¸¦ ÇÒ ¼ö ÀÖ´Â ÇÁ·Î±×·¥ÀÇ ¿¹´Â µÎ º¤ÅÍÀÇ ½ºÄ®¶óÄÚ°öÀ» °è»êÀÌ´Ù. ÁÖ¼®À» ºÙÀÎ Äڵ带 Á¦½ÃÇÑ´Ù.

/* ÄÄÆÄÀÏ ÇÏ·Á¸é gcc  -D_REENTRANT -lpthread */

#include <stdio.h>
#include <pthread.h>

/* ¾Ë¸ÂÀº ±¸Á¶Ã¼ ¼±¾ð */ 
typedef struct {
        double volatile *p_s;      /* ½ºÄ®¶ó °öÀÇ °øÀ¯ º¯¼ö */
        pthread_mutex_t *p_s_lock; /* º¯¼ö sÀÇ lock */
        int n;                     /* ¾²·¹µåÀÇ ¼ö */
        int nproc;                 /* ÀÌ¿ëÇÒ ¼ö ÀÖ´Â ÇÁ·Î¼¼¼­ÀÇ ¼ö */
        double *x;                 /* ù¹ø° º¤ÅÍÀÇ µ¥ÀÌÅÍ */
        double *y;                 /* µÎ¹ø° º¤ÅÍÀÇ µ¥ÀÌÅÍ */
        int l;                     /* º¤ÅÍÀÇ ±æÀÌ */
} DATA;

void *SMP_scalprod(void *arg)
{
        register double localsum;
        long i;
        DATA D = *(DATA *)arg;

        localsum = 0.0;

        /* °¢ ¾²·¹µå´Â i = D.n¿¡¼­ ºÎÅÍ ½ºÄ®¶ó °öÀ» ½ÃÀÛÇÑ´Ù. 
           D.n = 1, 2, ...
           D.nproc °ªÀ» °®´Â´Ù. Á¤È®È÷ D.nproc°³ÀÇ ¾²·¹µå°¡ ÀÖ±â 
           ¶§¹®¿¡ iÀÇ Áõ°¡ °°Àº D.nprocÀÌ´Ù. */

        for(i = D.n; i < D.l; i += D.nproc)
        localsum += D.x[i]*D.y[i];

        /* s¿¡ ´ëÇÑ lockÀ» °Ç´Ù ... */
        pthread_mutex_lock(D.p_s_lock);

        /* ... sÀÇ °ªÀ» ¹Ù²Û´Ù. ... */
        *(D.p_s) += localsum;

        /* ... ±×¸®°í lock¸¦ Á¦°ÅÇÑ´Ù. */
        pthread_mutex_unlock(D.p_s_lock);

        return NULL;
}

#define L 9     /* º¤ÅÍÀÇ Â÷¿ø */

int main(int argc, char **argv)
{
        pthread_t *thread;
        void *retval;
        int cpu, i;
        DATA *A;
        volatile double s = 0; /* °øÀ¯ º¯¼ö */ 
        pthread_mutex_t s_lock; 
        double x[L], y[L];

        if (argc != 2) {
                printf("usage: %s <number of CPU>\n", argv[0]);
                exit(1);
        }
        
        cpu = atoi(argv[1]);
        thread = (pthread_t *) calloc(cpu, sizeof(pthread_t));
        A = (DATA *) calloc(cpu, sizeof(DATA));

 
        for (i = 0; i < L; i++)
        x[i] = y[i] = i;

        /* lock º¯¼ö¸¦ ÃʱâÈ­ÇÑ´Ù. */
        pthread_mutex_init(&s_lock, NULL);

        for (i = 0; i < cpu; i++) {
                /* ±¸Á¶Ã¼¸¦ ÃʱâÈ­ÇÑ´Ù. */
                A[i].n = i; /* ¾²·¹µåÀÇ ¼ö */
                A[i].x = x;
                A[i].y = y;
                A[i].l = L;
                A[i].nproc = cpu; /* CPUÀÇ ¼ö */
                A[i].p_s = &s;
                A[i].p_s_lock = &s_lock;

                if (pthread_create(&thread[i], NULL, SMP_scalprod, 
                    &A[i])) {
                        fprintf(stderr, "%s: cannot make thread\n", 
                                argv[0]);
                        exit(1);
                }
        }

        for (i = 0; i < cpu; i++) {
                if (pthread_join(thread[i], &retval)) {
                        fprintf(stderr, "%s: cannot join thread\n", 
                                argv[0]);
                        exit(1);
                }
        }

        printf("s = %f\n", s);
        exit(0);
}

Copyright ¨Ï 1999, Matteo Dell'Omodarme

Published in Issue 48 of Linux Gazette, December 1999


ID
Password
Join
Love is in the offing. Be affectionate to one who adores you.


sponsored by andamiro
sponsored by cdnetworks
sponsored by HP

Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2007-05-09 13:15:59
Processing time 0.0033 sec