编写一个Pthreads程序实现一个“任务队列”。主线程启动用户指定数量的线程,这些线程进入条件等待状态。主线程生成一些任务(一定计算量),每生成一个新的任务,就用条件变量唤醒一个线程,当这个唤醒线程执行完任务时,回到条件等待状态。当主线程生成完所有任务,设置全局变量表示再没有要生成的任务了,并用一个广播唤醒所有线程。为了清晰起见,建议任务采用链表操作
可以自己手动改 Gen_work函数中的循环次数以改变任务计算量
计时头文件
不想看运行时间也可以不加,把GET_TIME注释掉即可
/* File: timer.h
*
* Purpose: Define a macro that returns the number of seconds that
* have elapsed since some point in the past. The timer
* should return times with microsecond accuracy.
*
* Note: The argument passed to the GET_TIME macro should be
* a double, *not* a pointer to a double.
*
* Example:
* #include "timer.h"
* . . .
* double start, finish, elapsed;
* . . .
* GET_TIME(start);
* . . .
* Code to be timed
* . . .
* GET_TIME(finish);
* elapsed = finish - start;
* printf("The code to be timed took %e seconds\n", elapsed);
*
* IPP: Section 3.6.1 (pp. 121 and ff.) and Section 6.1.2 (pp. 273 and ff.)
*/
#ifndef _TIMER_H_
#define _TIMER_H_
#include <sys/time.h>
/* The argument now should be a double (not a pointer to a double) */
#define GET_TIME(now) { \
struct timeval t; \
gettimeofday(&t, NULL); \
now = t.tv_sec + t.tv_usec/1000000.0; \
}
#endif
源程序代码
/*
*编写一个Pthreads程序实现一个“任务队列”。主线程启动用户指定数量的线程,
*这些线程进入条件等待状态。主线程生成一些任务(一定计算量),每生成一个新的任务,
*就用条件变量唤醒一个线程,当这个唤醒线程执行完任务时,回到条件等待状态。
*当主线程生成完所有任务,设置全局变量表示再没有要生成的任务了,并用一个广播唤醒所有线程。
*为了清晰起见,建议任务采用链表操作。
*/
#include<stdlib.h>
#include<stdio.h>
#include<pthread.h>
#include "time.h"
#include<unistd.h>
typedef struct list_node_s{//链表节点
int data;
struct list_node_s* next;
}list_node_s;
typedef struct work_queue{//任务队列
list_node_s* head;
list_node_s* tail;
}work_queue;
/************全局区************/
int thread_count;//线程数
int work_count;//任务量
int finished = 0;//所有任务生成完成标记
pthread_cond_t cond_var;//条件变量:没有要生成的任务了,广播唤醒所有线程
pthread_mutex_t mutex;//互斥访问任务队列,粗粒度锁
work_queue q;//任务队列
int* data;//任务数据集合
/*******************************/
int Init(work_queue *queue_p)
{
queue_p->head = (list_node_s*)malloc(sizeof(list_node_s));
queue_p->tail = queue_p->head;
queue_p->head->next = NULL;
return 1;
}
//入队
int Push(work_queue*queue_p,int value)
{
list_node_s* temp = (list_node_s*)malloc(sizeof(list_node_s));
temp->data = value;
temp->next = NULL;
queue_p->tail->next = temp;
queue_p->tail = temp;
return 1;
}
//出队
int Pop(work_queue*queue_p)
{
if(queue_p->head == queue_p->tail){//队列空
return -1;
}
list_node_s *p = queue_p->head->next;
if(p == NULL) return -1;
int index = p->data;
if(queue_p->tail == NULL) queue_p->tail = queue_p->head;
queue_p->head->next = p->next;
free(p);
return index;//返回任务号
}
void Usage(char prog_name[]) {
fprintf(stderr, "usage: %s ", prog_name);
fprintf(stderr, "<线程数> <主线程生成的任务量>\n");
exit(0);
}
//具体任务
long long Gen_work(int rank)
{
srand(0);
for(int i=0;i<1000/(rank+1);i++)
data[i] = rand();
long long sum = 0;
for(int i=0;i<1000/(rank+1);i++)
sum+=data[i];
return sum;
}
void *Thread_work(void* rank)
{
int my_rank = (int)rank;
while(1){
pthread_mutex_lock(&mutex);
if(finished){
if(q.head == q.tail || q.head->next == NULL){//所有任务已经被处理完了
pthread_mutex_unlock(&mutex);
break;
}else{
int index = Pop(&q);//返回任务ID
pthread_mutex_unlock(&mutex);
long long result = Gen_work(my_rank);//一定计算量的任务
if(index!=-1)
printf("thread %d finished task %2d, result: %lld\n",my_rank,index,result);
}
}else{
while(pthread_cond_wait(&cond_var,&mutex)!=0);
//等待mutex解锁 让线程进入条件等待状态
int index = Pop(&q);//返回任务ID
pthread_mutex_unlock(&mutex);
long long result = Gen_work(my_rank);//一定计算量的任务
if(index!=-1)
printf("thread %d finished task %d, result: %lld\n",my_rank,index,result);
}
}
}
int main(int argc,char* argv[])
{
if(argc != 3) Usage(argv[0]);
thread_count = strtol(argv[1],NULL,10);
work_count = strtol(argv[2],NULL,10);
pthread_t* thread_handles;
double start,finish;
Init(&q);
pthread_mutex_init(&mutex,NULL);
thread_handles = malloc(thread_count*sizeof(pthread_t));
data = malloc(100000*sizeof(int));
GET_TIME(start);
//启动用户指定数量的线程
for(int i=0;i<thread_count; i++)
pthread_create(&thread_handles[i], NULL,Thread_work, (void*)i);
//主线程生成一些任务
for(int i=0;i<work_count;i++){
pthread_mutex_lock(&mutex);
Push(&q,i);
pthread_cond_signal(&cond_var);//唤醒一个线程
pthread_mutex_unlock(&mutex);
}
finished = 1;
printf("%d tasks are created\n",work_count);
pthread_cond_broadcast(&cond_var);
for (int i = 0; i < thread_count; i++)
pthread_join(thread_handles[i], NULL);
GET_TIME(finish);
printf("run time:%.6f seoncds",finish-start);
pthread_cond_destroy(&cond_var);
pthread_mutex_destroy(&mutex);
free(thread_handles);
return 0;
}