wait()¿Í notify()

±Û : À±°æ±¸

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

/*
 * 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¿¡¼­ ½ÇÇà)
ÀÌ °æ¿ì¿¡´Â notify°¡ wait¿¡ ¾Õ¼­ ¿¬¼Ó ¹ß»ýÇÏ¿© ¹«½ÃµÇ¾ú±â ¶§¹®¿¡ ¸î¸î wait´Â ¹«ÇÑÈ÷ ±â´Ù¸®°Ô µÈ´Ù.(µ¥µå¶ô)
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(À¯´Ð½ºÀÇ pthread »ç¿ë)

ÀÌ ¼Ò½º ÄÚµå´Â POSIX.1c standard(draft 10) ¹öÀü¿¡ µû¸¥ °ÍÀ̹ǷΠ´Ù¸¥ ¹öÀüÀÇ °æ¿ì¿¡´Â Á¶±ÝÀÇ ¼öÁ¤ÀÌ ÇÊ¿äÇÏ´Ù.
/*
 * 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

condtest.c(Win32)

[PENDING]


1998³â 10¿ù 27ÀÏ¿¡ óÀ½ ¸¸µé¾îÁö°í, 1999³â 8¿ù 24ÀÏ¿¡ ÃÖÁ¾ º¯°æµÇ¾ú½À´Ï´Ù.

Æ©Å丮¾ó ÆäÀÌÁö·Î µ¹¾Æ°¡±â
Last modified: Tue Aug 24 13:55:54 1999