首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 操作系统 > UNIXLINUX >

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

2013-11-03 
(急求解答)多个生产者和多个消费者出现问题头文件Queue.h#include stdio.h#include stdlib.h#include

(急求解答)多个生产者和多个消费者出现问题
头文件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
生产者,消费者,多线程,Linux
[解决办法]
楼上说的是一个问题!最好初始化下,不用的时候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;
    }
    

热点排行