#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.\n", (int)(*((int*)(arg))));
pthread_mutex_lock(&mutex);
printf("consumer[%d] pthread_mutex_lock.\n", (int)(*((int*)(arg))));
while (g_value <= 0) {//防止虚假唤醒
printf("consumer[%d] begin wait.\n", (int)(*((int*)(arg))));
int ret = pthread_cond_wait(&cond, &mutex);
if (ret) {
printf("pthread_cond_wait error ret[%d].\n", ret);
return NULL;
}
printf("consumer[%d] end wait.\n", (int)(*((int*)(arg))));
}
--g_value;
printf("consumer[%d] g_value:[%d].\n", (int)(*((int*)(arg))), g_value);
pthread_mutex_unlock(&mutex);
printf("consumer[%d] pthread_mutex_unlock.\n", (int)(*((int*)(arg))));
return NULL;
}
void* consumer2(void* arg)
{
printf("consumer[%d] begin consume.\n", (int)(*((int*)(arg))));
pthread_mutex_lock(&mutex);
printf("consumer[%d] pthread_mutex_lock.\n", (int)(*((int*)(arg))));
while (g_value <= 0) {//防止虚假唤醒
printf("consumer[%d] begin wait.\n", (int)(*((int*)(arg))));
int ret = pthread_cond_wait(&cond, &mutex);
if (ret) {
printf("pthread_cond_wait error ret[%d].\n", ret);
return NULL;
}
printf("consumer[%d] end wait.\n", (int)(*((int*)(arg))));
}
--g_value;
printf("consumer[%d] g_value:[%d].\n", (int)(*((int*)(arg))), g_value);
pthread_mutex_unlock(&mutex);
printf("consumer[%d] pthread_mutex_unlock.\n", (int)(*((int*)(arg))));
return NULL;
}
void* producer(void* arg)
{
cout << "producer begin product." << endl;
pthread_mutex_lock(&mutex);
printf("producer pthread_mutex_lock.\n");
++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].\n", ret);
return NULL;
}
cout << "producer end pthread_cond_broadcast." << endl;
}
printf("producer begin pthread_mutex_unlock.\n");
int ret = pthread_mutex_unlock(&mutex);
if (ret) {
printf("pthread_mutex_unlock error ret[%d].\n", ret);
return NULL;
}
printf("producer end pthread_mutex_unlock.\n");
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].\n", 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].\n", ret);
return -1;
}
sleep(5);
ret = pthread_create(&tid_producer, NULL, &producer, NULL);
if (ret)
{
printf("pthread_create error ret[%d].\n", 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].\n", ret);
}
}
ret = join(tid_producer, NULL);
if (ret) {
printf("join error ret[%d].\n", ret);
return -1;
}
printf("pthread join success.\n");
return 0;
}