(急求解答)多个生产者和多个消费者出现问题

BruceZhang 2013-11-02 06:39:55
头文件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);


C文件 Queue.c
#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;
}



测试文件pro_con.c
#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;
}


Makefile文件
pro_con : Queue.o pro_con.o
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
...全文
166 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
BruceZhang 2013-11-02
  • 打赏
  • 举报
回复
运行时出现段错误或者是free掉了无效的内存,是什么原因?
max_min_ 2013-11-02
  • 打赏
  • 举报
回复
楼上说的是一个问题!最好初始化下,不用的时候destory掉! 第二个问题

  /*首先获取队列的锁*/
    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;
    }
    
Carl_CCC 2013-11-02
  • 打赏
  • 举报
回复
楼主要问什么问题啊? 不知道楼主的代码能不能运行,但线程锁,条件变量这些我没看到初始化是不对的。

23,128

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧