wait()¿Í notify()´Â µ¿ÀÏÇÑ Àá±Ý °´Ã¼ ÇÏ¿¡¼ µ¿±âÈµÇ¾î ½ÇÇàµÇ´Â ºí·Ï¿¡¼ ½ÇÇàµÉ ¼ö ÀÖ´Ù.
notify() ÀÌÈÄÀÇ ½ÇÇà ¼ø¼´Â ¸ÕÀú notify()¸¦ È£ÃâÇÑ ¾²·¹µå°¡ synchronized ºí·ÏÀ» ¹þ¾î³ ´ÙÀ½¿¡ wait()ÇÏ´Ù ±ú¾î³ ¾²·¹µåÀÇ ¼öÇàÀ» º¸ÀåÇÏ´Â ¼ø¼·Î µÈ´Ù.
Âü°í: Mesa ¹æ½Ä°ú Hoare ¹æ½Ä Mesa ¹æ½Ä¿¡¼´Â wait()ÇÏ´ø ¾²·¹µå°¡ ´Ù½Ã Àá±ÝÀ» ȹµæÇÏ´Â °ÍÀº ¼øÀüÈ÷ wait()ÇÏ´ø °´Ã¼ÀÇ Ã¥ÀÓÀÌ´Ù. Áï, notify()ÇÏ´ø ¾²·¹µå´Â wait()ÇÏ´Â °´Ã¼¸¦ Àá±ÝÀ» ȹµæÇÏ·Á°í ÇÏ´Â(½ºÄÉÁìµÇ·Á°í ÇÏ´Â) ¾²·¹µå ¸ñ·Ï¿¡ ¿Ã·ÁÁÙ »Ó, ÀÚ½ÅÀÇ ÀӰ迵¿ª(critical section)À» °è¼Ó ¼öÇàÇÑ ´ÙÀ½ ÀÓ°è ¿µ¿ªÀ» ¹þ¾î³ª¸é¼ Àá±ÝÀ» Ǭ´Ù. Hoare ¹æ½Ä¿¡¼´Â notify()ÇÏ´ø ¾²·¹µå°¡ Àá½Ã Àá±ÝÀ» Ç®°í Á¦¾î¸¦ ±ú¾î³¯ ¾²·¹µå¿¡°Ô ³Ñ°ÜÁØ´Ù. wait()ÇÏ´ø °´Ã¼°¡ ÀӰ迵¿ª ¼öÇàÀ» ¸¶Ä£ ÈÄ ´Ù½Ã notify()Çß´ø ¾²·¹µå¿¡°Ô Àá±Ý¿¡ ´ëÇÑ Á¦¾î¸¦ µ¹·ÁÁØ´Ù. Mesa ¹æ½ÄÀ» »ç¿ëÇÏ°Ô µÇ¸é ±ú¾î³ ¾²·¹µå°¡ ½ÇÇàµÇ±â Àü¿¡ ¾î¶² ´Ù¸¥ ¾²·¹µå°¡ Àá±ÝÀ» ȹµæÇÏ¿© ¼öÇàµÇ¸é¼ µ¥ÀÌÅ͸¦ º¯°æ½Ãų ¼ö ÀÖ´Â ´ÜÁ¡ÀÌ ÀÖ´Ù. ±×·¯³ª Hoare ¹æ½Ä¿¡ ºñÇØ ±¸ÇöÀÌ ÈξÀ ½±´Ù´Â ÀåÁ¡ÀÌ ÀÖ´Ù.
ÀÚ¹ÙÀÇ ±¸ÇöÀº Mesa ¹æ½ÄÀÌ´Ù. °¢ Àá±Ý °´Ã¼¿¡´Â ±â´Ù¸®´Â ¾²·¹µå ¸ñ·Ï(wait set)ÀÌ ÀÖ¾î¼ notify()¸¦ Çϸé wait set¿¡ ÀÖ´Â ¾²·¹µåµé Áß ÀÓÀÇÀÇ Çϳª¸¦ wait set¿¡¼ Áö¿ö¼ ´Ù½Ã ½ºÄÉÁ층µÉ ¼ö ÀÖµµ·Ï ÇÑ´Ù. ¹°·Ð notify()ÇÑ ¾²·¹µå°¡ ÀӰ迵¿ªÀ» ¹þ¾î³ª Àá±ÝÀ» Ç®Áö ¾Ê´Â ÇÑ ½ºÄÉÁ층µÈ ¾²·¹µå°¡ Àá±ÝÀ» ȹµæÇÒ ¼ö´Â ¾ø´Ù.
|
¾²·¹µå°¡ wait()¿¡ µµ´ÞÇϸé Àá±Ý °´Ã¼¸¦ Ç®°í notify()µÇ±â¸¦ ±â´Ù¸®´Ù°¡ notify()·Î ÀÎÇØ ±ú¾î³ ´ÙÀ½¿¡ ÀÚµ¿À¸·Î ´Ù½Ã Àá±Ý °´Ã¼¸¦ Àá±×°í ³ª¸ÓÁö synchronized ºí·Ï ³»ºÎ¸¦ ¼öÇàÇÏ°Ô µÈ´Ù.
À¯´Ð½º POSIX ¾²·¹µå ÇÁ·Î±×·¡¹ÖÀ» ÇÒ ¶§ÀÇ pthread_cond_signal()°ú pthread_cond_wait() ÇÔ¼ö°¡ °¢°¢ ÀÚ¹ÙÀÇ notify(), wait()¿¡ ÇØ´çÇÑ´Ù°í º¼ ¼ö ÀÖ´Ù.
/* * WaitTest.java * Copyright 1998 yoonforh@yahoo.com */ class WaitTest { int value; class Putter extends Thread { Object locker; public Putter(Object locker) { this.locker=locker; } public void run() { doPut(locker); } } void doPut(Object obj) { synchronized (obj) { value++; System.out.println("PUTTER["+Thread.currentThread().getName()+"]:value="+value); notify(); System.out.println("PUTTER["+Thread.currentThread().getName()+"]:after notify"); } } class Getter extends Thread { Object locker; public Getter(Object locker) { this.locker=locker; } public void run() { doGet(locker); } } void doGet(Object obj) { synchronized (obj) { System.out.println("GETTER["+Thread.currentThread().getName()+"]:before wait"); try { wait(); } catch (InterruptedException ie) { System.out.println("Interrupted..."); } value--; System.out.println("GETTER["+Thread.currentThread().getName()+"]:value="+value); } } public WaitTest() { Thread one = new Putter(this); Thread two = new Putter(this); Thread three = new Putter(this); Thread four = new Putter(this); Thread five = new Putter(this); Thread six = new Getter(this); Thread seven = new Getter(this); Thread eight = new Getter(this); Thread nine = new Getter(this); Thread ten = new Getter(this); six.start(); seven.start(); eight.start(); nine.start(); ten.start(); one.start(); two.start(); three.start(); four.start(); five.start(); } public static void main(String args[]) { new WaitTest(); } }½ÇÇà °á°ú ¿¹ 1(Digital Unix 4.0B(1CPU) JDK 1.1.6¿¡¼ ½ÇÇà)
GETTER[Thread-7]:before wait GETTER[Thread-8]:before wait GETTER[Thread-9]:before wait GETTER[Thread-10]:before wait GETTER[Thread-11]:before wait PUTTER[Thread-2]:value=1 PUTTER[Thread-2]:after notify GETTER[Thread-7]:value=0 PUTTER[Thread-3]:value=1 PUTTER[Thread-3]:after notify PUTTER[Thread-4]:value=2 PUTTER[Thread-4]:after notify GETTER[Thread-8]:value=1 PUTTER[Thread-5]:value=2 PUTTER[Thread-5]:after notify GETTER[Thread-9]:value=1 PUTTER[Thread-6]:value=2 PUTTER[Thread-6]:after notify GETTER[Thread-10]:value=1 GETTER[Thread-11]:value=0½ÇÇà °á°ú ¿¹ 2(Digital Unix 4.0B(1CPU) JDK 1.1.6¿¡¼ ½ÇÇà)
GETTER[Thread-7]:before wait PUTTER[Thread-2]:value=1 PUTTER[Thread-2]:after notify PUTTER[Thread-3]:value=2 PUTTER[Thread-3]:after notify <- waitÇÏ°í ÀÖ´Â ¾²·¹µå°¡ ¾ø´Âµ¥ notify PUTTER[Thread-4]:value=3 PUTTER[Thread-4]:after notify <- waitÇÏ°í ÀÖ´Â ¾²·¹µå°¡ ¾ø´Âµ¥ notify GETTER[Thread-7]:value=2 GETTER[Thread-8]:before wait PUTTER[Thread-5]:value=3 PUTTER[Thread-5]:after notify GETTER[Thread-9]:before wait PUTTER[Thread-6]:value=4 PUTTER[Thread-6]:after notify GETTER[Thread-10]:before wait <- ÀÌ ¾²·¹µå´Â ¹«ÇÑÈ÷ ±â´Ù¸®°Ô µÈ´Ù. GETTER[Thread-8]:value=3 GETTER[Thread-11]:before wait <- ÀÌ ¾²·¹µå´Â ¹«ÇÑÈ÷ ±â´Ù¸®°Ô µÈ´Ù. GETTER[Thread-9]:value=2
/* * condtest.c * Copyright 1998 yoonforh@yahoo.com */ #include <pthread.h> #include <stdio.h> /******************************** DEFINES *****************************/ #define NUMTHREADS 10 #define NUM_PUTTERS 5 #define NUM_GETTERS 5 pthread_mutex_t mutex; pthread_cond_t cond; int value=0; main(int argc, char **argv) { int numThr; pthread_t threadId[NUMTHREADS]; pthread_attr_t threadAttr; void *Getters(); void *Putters(); int i; int *status; pthread_mutexattr_t *m_attr; pthread_condattr_t *c_attr; m_attr=(pthread_mutexattr_t *) malloc(sizeof(pthread_mutexattr_t)); c_attr=(pthread_condattr_t *) malloc(sizeof(pthread_condattr_t)); pthread_mutexattr_init(m_attr); pthread_condattr_init(c_attr); pthread_mutex_init(&mutex , m_attr); pthread_cond_init(&cond , c_attr); numThr = NUM_PUTTERS + NUM_GETTERS; if (numThr > NUMTHREADS) exit(0); pthread_attr_init(&threadAttr); for (i = 0; i < NUM_PUTTERS; ++i) pthread_create(&threadId[i], &threadAttr, Getters, NULL); for (i= NUM_PUTTERS ; i < numThr; ++i) pthread_create(&threadId[i], &threadAttr, Putters, NULL); for (i = 0; i < numThr; ++i) pthread_join(threadId[i],(void**) &status); exit(0); } void * Putters(void *pThrArg) { pthread_t Tid; int i; char msg[256]; Tid = pthread_self(); pthread_mutex_lock(&mutex); value++; fprintf(stderr, "PUTTER[%d]:value=%d\n", Tid, value); pthread_cond_signal(&cond); fprintf(stderr, "PUTTER[%d]:after cond_signal\n", Tid); pthread_mutex_unlock(&mutex); return(NULL); } void * Getters(void *pThrArg) { volatile int i; int nmsgs; int Rc; char msg[256]; pthread_t Tid; Tid = pthread_self(); pthread_mutex_lock(&mutex); fprintf(stderr, "GETTER[%d]:before cond_wait\n", Tid); pthread_cond_wait(&cond, &mutex); value--; fprintf(stderr, "GETTER[%d]:value=%d\n", Tid, value); pthread_mutex_unlock(&mutex); return(NULL); }½ÇÇà °á°ú ¿¹(Digital Unix 4.0B(1CPU)¿¡¼ ½ÇÇà)
GETTER[1073797136]:before cond_wait GETTER[1073840176]:before cond_wait GETTER[1073841552]:before cond_wait GETTER[1073842928]:before cond_wait GETTER[1073844304]:before cond_wait PUTTER[1073845680]:value=1 PUTTER[1073845680]:after cond_signal PUTTER[1073889328]:value=2 PUTTER[1073889328]:after cond_signal PUTTER[1073890704]:value=3 PUTTER[1073890704]:after cond_signal PUTTER[1073892080]:value=4 PUTTER[1073892080]:after cond_signal PUTTER[1073893456]:value=5 PUTTER[1073893456]:after cond_signal GETTER[1073797136]:value=4 GETTER[1073840176]:value=3 GETTER[1073841552]:value=2 GETTER[1073842928]:value=1 GETTER[1073844304]:value=0