实验二 编写Pthreads程序实现“任务队列”

编写一个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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值