linux下出产者与消费者C实现
副标题#e#
最近做毕设涉及到了出产者与消费者模子,这个东东只在操纵系统课程上有点印象,于是花了点时间看了下《unix情况高级编程 》的线程部门,在此记录一下。
1.多线程的观念就不多说了,pthread.h头文件中包括的几个根基观念及函数:
pthread_t————线程ID数据范例,线程ID只在它所属的历程情况中有效;
int pthread_create(pthread_t *tidp, const pthread_attr_t *attr, func(void), arg)————建设新的线程,若乐成返回0配置tidp指向的单位为新线程的线程IDattr用来配置线程属性,一般默认为NULLfunc为新线程挪用的进口函数,该函数只能有一个无范例指针参数arg,若要向函数通报多个参数,需要将所有参数放到一个布局中,再把布局地点通报给arg
pthread_t pthread_self(void)————获取自身线程ID
void pthread_exit(void *rval_ptr)———终止本线程,用rval_ptr指向的值作为退出码
int pthread_join(pthread_t thread, void **rval_ptr)————挪用该函数的线程将阻塞,直到thread线程挪用pthread_exit、从启动例程返回或被打消,rval_ptr将包括返回码
int pthread_cancel(pthread_t tid)————该函数用来请求打消统一历程中的其他线程
2.线程同步————互斥量、读写锁,条件变量
读写锁即共享——独有锁,适合于读的次数远大于写的环境,较量好领略,就不多说了。
条件变量由互斥量掩护,线程在改变条件状态之前必需先锁定互斥量。
出产者与消费者模子用到了互斥量和条件变量,对行罗列办读写,下面直接上代码:
行列操纵(数据布局的内容),回收链式布局:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <pthread.h>
#define MAXLENGTH 10 //the maxlength of queue
typedef char * datatype;
typedef struct node { //define node
datatype name;
struct node *next;
} node;
typedef struct queue { //define queue
node *front, *rear;
int len;
} queue;
void queue_init(queue *q)
{
q->front = q->rear = NULL;
q->len = 0;
}
void queue_put(queue *q, datatype new_name) //入队
{
node *mynode = (node *)malloc(sizeof(node));
mynode->name = new_name;
mynode->next = NULL;
if (q->rear)
q->rear->next = mynode;
q->rear = mynode;
if (q->front == NULL)
q->front = mynode;
q->len++;
}
datatype queue_get(queue *q) //出队
{
node *mynode;
datatype myname;
if (q->front != NULL)
mynode = q->front;
myname = mynode->name;
q->front = q->front->next;
q->len--;
free(mynode);
return myname;
}
void queue_print(queue *q) //print queue
{
node *tmp = q->front;
while(tmp != NULL)
{
printf("%s ", tmp->name);
tmp = tmp->next;
}
printf("n");
}
#p#副标题#e#
出产者与消费者函数:
/*define mutex and condtion var*/
pthread_cond_t q_not_full = PTHREAD_COND_INITIALIZER;
pthread_cond_t q_not_empty = PTHREAD_COND_INITIALIZER;
pthread_mutex_t qlock = PTHREAD_MUTEX_INITIALIZER;
/*
* producer function
*/
void producer(void *q)
{
// printf("start porducer:n");
queue *qt = q; //传入的行列
while(1)
{
pthread_mutex_lock(&qlock);
// printf("producer has locked the qlockn");
if(qt->len >= MAXLENGTH) //queue is full
{
// printf("producer is going to waitingn");
pthread_cond_wait(&q_not_full, &qlock);
}
queue_put(qt, "* ");
// printf("after producer: queue's length is %dn", qt->len);
pthread_mutex_unlock(&qlock);
pthread_cond_signal(&q_not_empty);
// printf("producer has unlocked the qlockn");
// sleep(1);
}
}
/*
* consumer function
*/
void consumer(void *q)
{
// printf("start consumer:n");
queue *qt = q;
while(1)
{
pthread_mutex_lock(&qlock);
// printf("consumer has locked the qlockn");
if(qt->len <= 0) //queue is empty
{
// printf("consumer is going to waitingn");
pthread_cond_wait(&q_not_empty, &qlock);
}
datatype back_name = queue_get(qt);
// printf("after consumer, queue's length is %dn", qt->len);
pthread_mutex_unlock(&qlock);
pthread_cond_signal(&q_not_full);
// now process the back_name
// printf("cousumer has unlocked the qlockn");
// sleep(1);
}
}
#p#分页标题#e#
主函数(测试):
//gcc编译时加上-lpthread
int main() {
pthread_t tid1, tid2;
queue *q=(queue *)malloc(sizeof(queue));
queue_init(q);
// queue_put(q, "one");
// queue_put(q, "two");
// queue_put(q, "three");
// queue_get(q);
// printf("len = %dn", q->len);
// queue_print(q);
long stime = clock();
long etime = clock();
pthread_create(&tid1, NULL, (void *)producer, (void *)q);
pthread_create(&tid2, NULL, (void *)consumer, (void *)q);
while((float)(etime-stime)/CLOCKS_PER_SEC < 0.00001)
{
etime = clock();
}
return 0;
}
From:cnblogs xfan