cond & mutex 를 이용한 쓰레드 동기화 문제
글쓴이: air74 / 작성시간: 화, 2005/02/15 - 9:42오전
쓰레드를 이용하여 producer/consumer 구조로 프로그램을 개발 하려고 합니다.
예상 하는 동작 순서는
producer->consumer->producer->consumer ......순으로 반복 되어야 합니다.
하지만 실제적으로는
producer->consumer 가 한번만 수행이 되고는 다시 producer 가 깨어나질 않습니다.
혹시 sleep 을 안 주어서 그런것인지?? pthread_cond_signal을 사용하는데 sleep 이 필요 한것인지 ..
더욱더 정확하고 성능에 지장이 없는 동기화 방법에 대한 조언 좀 해주세요.
다음은 간략한 소스코드 입니다.
typedef struct shared_buffer {
pthread_mutex_t lock;
pthread_cond_t cond;
} shared_buffer_t;
void sb_init(shared_buffer_t *sb) {
pthread_mutex_init(&sb->lock, NULL); /* lock ... */
pthread_cond_init(&sb->cond, NULL); /* cond ... */
}
void sb_destroy(shared_buffer_t *sb) {
pthread_mutex_destroy(&sb->lock); /* lock .. */
pthread_cond_destroy(&sb->cond); /* cond .. */
}
void producer(shared_buffer_t *sb) {
while (TRUE) {
pthread_mutex_lock (&sb->lock);
pthread_cond_wait(&sb->cond, &sb->lock);
printf("producer\n");
pthread_cond_signal (&sb->cond);
pthread_mutex_unlock(&sb->lock);
}
}
main() {
pthread_t th1; /* ... thread */
shared_buffer_t sb; /* .. ... */
sb_init(&sb);
pthread_create(&th1, NULL, (void *) producer, &sb); /* producer .. */
usleep(1);
while (TRUE) { /* consumer 역할을 수행 */
pthread_mutex_lock(&sb.lock);
pthread_cond_signal(&sb.cond);
pthread_cond_wait(&sb.cond, &sb.lock);
printf("consumer\n");
pthread_mutex_unlock (&sb.lock);
//usleep(0); ---> 이것이 필요 한지? 가급적이면 사용안했으면합니다.
}
pthread_join(th1, NULL);
sb_destroy(&sb);
}Forums:


[code:1]#include <pthread.h>#def
#include <pthread.h> #define TRUE 1 #define FALSE 0 typedef struct shared_buffer { pthread_mutex_t lock; pthread_cond_t condF, condE; } shared_buffer_t; void sb_init(void *vp) { shared_buffer_t *sb; sb = (shared_buffer_t *)vp; pthread_mutex_init(&sb->lock, NULL); /* lock ... */ pthread_cond_init(&sb->condF, NULL); /* cond ... */ pthread_cond_init(&sb->condE, NULL); /* cond ... */ } void sb_destroy(void *vp) { shared_buffer_t *sb; sb = (shared_buffer_t *)vp; pthread_mutex_destroy(&sb->lock); /* lock .. */ pthread_cond_destroy(&sb->condF); /* cond .. */ pthread_cond_destroy(&sb->condE); /* cond .. */ } volatile int xxx; void producer(void *vp) { shared_buffer_t *sb; sb = (shared_buffer_t *)vp; while (TRUE) { pthread_mutex_lock (&sb->lock); while ( xxx != 0 ) { //printf("wait for CONSUME %d\n", xxx); pthread_cond_wait(&sb->condF, &sb->lock); } printf("PRODUCE\n"); xxx++; pthread_mutex_unlock(&sb->lock); pthread_cond_signal (&sb->condE); } } void consumer(void *vp) { shared_buffer_t *sb; sb = (shared_buffer_t *)vp; while (TRUE) { pthread_mutex_lock(&sb->lock); while ( xxx == 0 ) { //printf("wait for produce %d\n", xxx); pthread_cond_wait(&sb->condE, &sb->lock); } printf("CONSUME\n"); xxx--; pthread_mutex_unlock (&sb->lock); pthread_cond_signal(&sb->condF); } } main() { pthread_t th1, th2,th3; /* ... thread */ shared_buffer_t sb; /* .. ... */ xxx = 0; sb_init(&sb); pthread_create(&th1, NULL, (void *) producer, &sb); /* producer .. */ // pthread_create(&th3, NULL, (void *) producer, &sb); /* producer .. */ pthread_create(&th2, NULL, (void *) consumer, &sb); /* consumer .. */ pthread_join(th1, NULL); pthread_join(th2, NULL); // pthread_join(th3, NULL); sb_destroy(&sb); }multiple producer들인 경우와 consumer가 다수개인 경우도 테스트해보세요.
천천히 읽어보시기 바랍니다.
sleep() 시리즈(usleep, sleep,...)를 넣어서 동기화하는 것은 아주 위험한 방법입니다. 아니고, ... 동기화에, 사용할 수 없는 것입니다.
또한 pthread_cond_wait() man 페이지를 잘 읽어보세요.
pthread_cond_wait()가 블록상태(block)에서 탈출하는 경우는 pthread_cond_signal()에 의해서만은 아니며, 이를 고려한 코딩을 해야합니다.
------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.
답변 감사 합니다. ^^
훌륭한 답변 감사 드립니다.
좋은 하루 되세요. ^^
어설푼 이..
이런식으로 하셔야 합니다.~~
#include <stdio.h> #include <unistd.h> #include <pthread.h> typedef struct shared_buffer { pthread_mutex_t lock; pthread_cond_t cond; } shared_buffer_t; void sb_init(shared_buffer_t *); void sb_destroy(shared_buffer_t *); void * producer(void *); void sb_init(shared_buffer_t *sb) { pthread_mutex_init(&sb->lock, NULL); pthread_cond_init(&sb->cond, NULL); } void sb_destroy(shared_buffer_t *sb) { pthread_mutex_destroy(&sb->lock); pthread_cond_destroy(&sb->cond); } int iFlag1 = 1; int iFlag2 = 0; void * producer(void * info) { shared_buffer_t * sb = (shared_buffer_t *)info; int i = 0; while(i < 100000) { pthread_mutex_lock(&sb->lock); while(iFlag1 == 0) pthread_cond_wait(&sb->cond, &sb->lock); printf("[%d]producer\n", i++); iFlag1 = 0; iFlag2 = 1; pthread_cond_signal(&sb->cond); pthread_mutex_unlock(&sb->lock); } } int main(int argc, char ** argv) { pthread_t th1; shared_buffer_t sb; sb_init(&sb); pthread_create(&th1, NULL, &producer, (void *)&sb); int i = 0; while(i < 100000) { pthread_mutex_lock(&sb.lock); while(iFlag2 == 0) pthread_cond_wait(&sb.cond, &sb.lock); printf("[%d]consumer\n", i++); iFlag1 = 1; iFlag2 = 0; pthread_cond_signal(&sb.cond); pthread_mutex_unlock(&sb.lock); } pthread_join(th1, NULL); sb_destroy(&sb); return 0; }내일은 내일일뿐.....
댓글 달기