(急求解答)多个生产者和多个消费者出现问题
头文件Queue.h
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <pthread.h>
typedef int DataType;
/*定义消费结束标志*/
#define OVER -1
/*定义队列数据结构*/
typedef struct _Queue
{
DataType data;
struct _Queue *next;
pthread_mutex_t lock; /* 互斥体lock 用于对缓冲区的互斥操作 */
pthread_cond_t notempty; /* 缓冲区非空的条件变量 */
}QueueNode, *Queue;
/*定义数据操作*/
void queue_init(Queue *queue_head);
int queue_is_empty(Queue queue_head);
int queue_insert(Queue queue_head, DataType value);
int queue_delete(Queue queue_head);
void queue_destory(Queue queue_head);
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <pthread.h>
#include <unistd.h>
#include "Queue.h" /*包含队列定义头文件*/
/*队列的初始化*/
void queue_init(Queue *queue_head)
{
/*队列的头节点*/
*queue_head = (QueueNode*)malloc(sizeof(QueueNode));
if (*queue_head == NULL)
{
perror("memory allocation failure");
return;
}
/*头节点用于记录队列中的节点个数*/
(*queue_head) -> data = 0;
/*circle list*/
/*初始时队列为空(只有一个节点)*/
(*queue_head) -> next = *queue_head;
}
/*判断队列是否为空*/
int queue_is_empty(Queue queue_head)
{
return queue_head -> data == 0 ? 1 : 0;
}
/*向队列中插入元素(生产者)*/
int queue_insert(Queue queue_head, DataType value)
{
QueueNode *new_node = NULL;
QueueNode *temp = NULL;
temp = queue_head;
/*首先获取队列的锁*/
pthread_mutex_lock(&queue_head -> lock);
new_node = (QueueNode*)malloc(sizeof(QueueNode));
if (new_node == NULL)
{
perror("memory allocation failure");
return -1;
}
/*初始化新节点*/
new_node -> data = value;
new_node -> next = queue_head;
/*采用头插法向队列中插入新节点*/
while (temp -> next != queue_head)
temp = temp -> next;
temp -> next = new_node;
queue_head -> data++;
printf("producer ----> %d\n", value);
/*信号表明队列不为空*/
pthread_cond_signal(&queue_head -> notempty);
/*释放锁*/
pthread_mutex_unlock(&queue_head -> lock);
usleep(1);
//usleep(300 * 1000);
return 0;
}
/*删除队列中的节点(消费者)*/
int queue_delete(Queue queue_head)
{
QueueNode *old_node = NULL;
DataType queue_value;
if (queue_head == NULL)
{
return -2;
}
/*获取队列锁*/
pthread_mutex_lock(&queue_head -> lock);
/*如果队列为空,则需要等待(线程睡眠,并释放锁)*/
if (queue_is_empty(queue_head))
{
pthread_cond_wait(&queue_head -> notempty, &queue_head -> lock);
}
/*队列不为空之后删除队列中的元素*/
old_node = queue_head -> next;
queue_head -> next = queue_head -> next -> next;
queue_head -> data--;
if (old_node != NULL)
{
queue_value = old_node -> data;
printf("%d ----> consumer\n", queue_value);
free(old_node);
old_node = NULL;
}
/*释放锁*/
pthread_mutex_unlock(&queue_head -> lock);
usleep(1);
//usleep(600 * 1000);
return queue_value;
}
/*销毁队列*/
void queue_destory(Queue queue_head)
{
QueueNode *temp = NULL;
QueueNode *del_node = NULL;
if (queue_head == NULL)
{
return;
}
temp = queue_head -> next;
/*从队列头开始依次删除队列中的各个节点*/
while (temp != queue_head)
{
del_node = temp;
temp = temp -> next;
free(del_node);
}
free(queue_head);
queue_head = NULL;
return;
}
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <pthread.h>
#include <sys/time.h>
#include <unistd.h>
#include "Queue.h"
/*生产者生产总数*/
#define PRO_NUM 10000
int flag = 1;
/*模拟生产者和消费者*/
void* producer(void *data);
void* consumer(void *data);
void* producer2(void *data);
Queue queue_head = NULL;
int main(int argc, char **argv)
{
pthread_t th_a, th_b;
pthread_t th_c, th_d;
void *retval;
struct timeval start;
struct timeval end;
unsigned long timer;
queue_init(&queue_head);
if (queue_head == NULL)
{
perror("memory allocation failure");
return -1;
}
gettimeofday(&start,NULL);
/* 创建生产者和消费者线程*/
pthread_create(&th_a, NULL, producer, 0);
usleep(10);
pthread_create(&th_b, NULL, consumer, 0);
pthread_create(&th_c, NULL, producer2, 0);
usleep(10);
pthread_create(&th_d, NULL, consumer, 0);
/* 等待两个线程结束*/
pthread_join(th_a, &retval);
pthread_join(th_b, &retval);
pthread_join(th_c, &retval);
pthread_join(th_d, &retval);
gettimeofday(&end,NULL);
/*得到的时间是微秒级*/
timer = 1000000 * (end.tv_sec - start.tv_sec) + end.tv_usec - start.tv_usec;
printf("timer = %ld us\n",timer);
return 0;
}
void* producer(void *data)
{
int i = 1;
for (i = 1; i < PRO_NUM / 2; i++)
{
queue_insert(queue_head, i);
}
/*插入生产者生产结束标志*/
queue_insert(queue_head, OVER);
return NULL;
}
void* producer2(void *data)
{
int i = 1;
for (i = PRO_NUM / 2; i < PRO_NUM + 1; i++)
{
queue_insert(queue_head, i);
}
/*插入生产者生产结束标志*/
queue_insert(queue_head, OVER);
return NULL;
}
void* consumer(void *data)
{
int result;
while (1)
{
result = queue_delete(queue_head);
/*消费结束标志*/
if (result == OVER)
{
if (flag == 1)
{
flag = 2;
continue;
}
else if (flag == 2)
{
break;
}
}
}
return NULL;
}
pro_con : Queue.o pro_con.o生产者,消费者,多线程,Linux
gcc -o pro_con Queue.o pro_con.o -lpthread
Queue.o : Queue.h Queue.c
gcc -c Queue.c
pro_con.o : Queue.h pro_con.c Queue.c
gcc -c pro_con.c Queue.c -lpthread
run:
./pro_con > result.txt
clean:
rm pro_con.o Queue.o result.txt pro_con
/*首先获取队列的锁*/
pthread_mutex_lock(&queue_head -> lock);
new_node = (QueueNode*)malloc(sizeof(QueueNode));
if (new_node == NULL)
{
perror("memory allocation failure");
pthread_mutex_unlock(&queue_head -> lock);
//失败的时候这句也是需要的!前面枷锁了,后面不管什么情况,都是需要解锁的!
return -1;
}