#if 0 Linux实现生产者消费者模型 1. 防止虚假唤醒 2. 唤醒线程的时机很重要,否则会导致线程多次访问锁,影响性能 #endif #include <unistd.h> #include <stdio.h> #include <iostream> #include <pthread.h> using namespace std; int g_value = 0; pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t cond = PTHREAD_COND_INITIALIZER; void* consumer1(void* arg) { printf("consumer[%d] begin consume. ", (int)(*((int*)(arg)))); pthread_mutex_lock(&mutex); printf("consumer[%d] pthread_mutex_lock. ", (int)(*((int*)(arg)))); while (g_value <= 0) {//防止虚假唤醒 printf("consumer[%d] begin wait. ", (int)(*((int*)(arg)))); int ret = pthread_cond_wait(&cond, &mutex); if (ret) { printf("pthread_cond_wait error ret[%d]. ", ret); return NULL; } printf("consumer[%d] end wait. ", (int)(*((int*)(arg)))); } --g_value; printf("consumer[%d] g_value:[%d]. ", (int)(*((int*)(arg))), g_value); pthread_mutex_unlock(&mutex); printf("consumer[%d] pthread_mutex_unlock. ", (int)(*((int*)(arg)))); return NULL; } void* consumer2(void* arg) { printf("consumer[%d] begin consume. ", (int)(*((int*)(arg)))); pthread_mutex_lock(&mutex); printf("consumer[%d] pthread_mutex_lock. ", (int)(*((int*)(arg)))); while (g_value <= 0) {//防止虚假唤醒 printf("consumer[%d] begin wait. ", (int)(*((int*)(arg)))); int ret = pthread_cond_wait(&cond, &mutex); if (ret) { printf("pthread_cond_wait error ret[%d]. ", ret); return NULL; } printf("consumer[%d] end wait. ", (int)(*((int*)(arg)))); } --g_value; printf("consumer[%d] g_value:[%d]. ", (int)(*((int*)(arg))), g_value); pthread_mutex_unlock(&mutex); printf("consumer[%d] pthread_mutex_unlock. ", (int)(*((int*)(arg)))); return NULL; } void* producer(void* arg) { cout << "producer begin product." << endl; pthread_mutex_lock(&mutex); printf("producer pthread_mutex_lock. "); ++g_value; cout << "producer g_value: " << g_value << endl; if (g_value > 0) { cout << "producer begin pthread_cond_broadcast." << endl; int ret = pthread_cond_broadcast(&cond); if (ret) { printf("pthread_cond_broadcast error ret[%d]. ", ret); return NULL; } cout << "producer end pthread_cond_broadcast." << endl; } printf("producer begin pthread_mutex_unlock. "); int ret = pthread_mutex_unlock(&mutex); if (ret) { printf("pthread_mutex_unlock error ret[%d]. ", ret); return NULL; } printf("producer end pthread_mutex_unlock. "); return NULL; } int join(pthread_t tid, void **retval) { int ret = pthread_join(tid, retval); if (ret) { return ret; } else { return 0; } } int main() { pthread_t tid_consumer[2] = {0}; pthread_t tid_producer = 0; int ret = -1; int _consumer1 = 1; ret = pthread_create(&tid_consumer[0], NULL, &consumer1, (void*)(&_consumer1)); if (ret) { printf("pthread_create error ret[%d]. ", ret); return -1; } sleep(1); int _consumer2 = 2; ret = pthread_create(&tid_consumer[1], NULL, &consumer2, (void*)(&_consumer2)); if (ret) { printf("pthread_create error ret[%d]. ", ret); return -1; } sleep(5); ret = pthread_create(&tid_producer, NULL, &producer, NULL); if (ret) { printf("pthread_create error ret[%d]. ", ret); return -1; } sleep(2); for (int i = 0; i < sizeof(tid_consumer)/sizeof(tid_consumer[0]); ++i) { ret = join(tid_consumer[i], NULL); if (ret) { printf("join error ret[%d]. ", ret); } } ret = join(tid_producer, NULL); if (ret) { printf("join error ret[%d]. ", ret); return -1; } printf("pthread join success. "); return 0; }