多线程排序程序

这篇博客介绍了一个使用多线程进行数组排序的程序,通过将数组分成两部分,每个部分由一个线程进行冒泡排序。文章详细阐述了如何定义结构存储排序参数,实现简单的冒泡排序,以及如何对程序计时。此外,还讨论了在Linux环境下使用gcc编译多线程程序时遇到的问题,如需要链接libpthread.a库,并解析了pthread_create函数的使用注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

程序描述

此程序实现了多线程的数组排序,可将一个数组拆分为两部分交由两个线程来排序,最后由父进程对其总和。

程序功能实现代码预览

定义一个结构来存排序算法所需要的参数

typedef struct //结构体用来存排序算法需要的参数
{
    int start;
    int end;
}Para;

一个简单的冒泡排序

void sort(Para* para){
    int i,j,temp;
    for(i=para->start;i<para->end;i++){
        for(j=para->end;j>i;j--){
            if(elem[j]<elem[j-1]){
                temp=elem[j];
                elem[j]=elem[j-1];
                elem[j-1]=temp;
            }
        }
    }
    pthread_exit(0);
}

实现对程序计时

int t_start=clock();
int t_end=clock();

将上面的代码分别放在程序首尾,最后相减即可得出运行时间

printf("耗时:%d\n", t_end-t_start);

注:此时间为CPU时间,两个核的话会把两个核的时间加起来。可以在程序名前面加time即可最后得出各种运行时间。

time ./a.out

创建两个线程

pthread_t tid1,tid2;  //线程的identifier
pthread_attr_t attr;  //线程属性

pthread_attr_init(&attr); //初始化默认线程属性

/**
 * 创建执行线程
 */
pthread_create(&tid1,&attr,(void *)sort,&para1); 
pthread_create(&tid2,&attr,(void *)sort,&para2);

重难点解析

关于gcc编译

由于pthread 库不是 Linux 系统默认的库,连接时需要使用静态库 libpthread.a,所以在使用pthread_create()创建线程,以及调用 pthread_atfork()函数建立fork处理程序时,需要链接该库。

gcc ./MultithreadsSort.c -lpthread

关于pthread_create

在使用这个方法时,第四个参数非常容易报错,原因是其为void * 类型,所以定义此类方法时参数要定义为void * 类型,然后再在方法中对参数进行格式转换。

void *sort(void * p){
    Para * para=(Para*)p;
    ...
}

完整代码

#include <stdio.h>
#include <pthread.h>
#include <time.h>

#define LENGTH 5000 //宏定义数组长度
#define MAX 100000   //宏定义数取值范围

typedef struct //结构体用来存排序算法需要的参数
{
    int start;
    int end;
}Para;

int elem[LENGTH]; //存随机数
int res[LENGTH];  //存排序结果

void initElem(); //初始化数组,向其中填指定范围的随机数
void *sort(void * p);   //排序程序
void printElenm(int [LENGTH]);  //打印数组用以检验是否排序成功
void merge();  //将elem的结果merge到res中

int main(){

    initElem(); //初始化数组并填入随机数
    /**
     * 设定两个线程各自排序的起止点
     */
    Para para1={0,LENGTH/2};
    Para para2={LENGTH/2+1,LENGTH-1};
    Para para3={0,LENGTH-1};

    pthread_t tid1,tid2;  //线程的identifier
    pthread_attr_t attr;  //线程属性

    pthread_attr_init(&attr); //初始化默认线程属性

    int t_start=clock(); //开始时间
    printf("多线程排序%d 时开始\n", t_start);

    /**
     * 创建执行线程
     */
    pthread_create(&tid1,&attr,sort,&para1); 
    pthread_create(&tid2,&attr,sort,&para2);

    /**
     * 等待线程结束
     */
    pthread_join(tid1,NULL);
    pthread_join(tid2,NULL);

    merge();  //整合
    //输出结果来验证
    //printElenm(res); 
    int t_end=clock();//结束时刻
    printf("多线程排序%d 时结束\n", t_end);
    printf("多线程排序耗时:%d\n", t_end-t_start); //计算程序运行消耗的时间

    /**
     * 接下来尝试单线程排序
     */
    initElem(); //首先还是初始化数组

    t_start=clock(); //开始时间
    printf("普通排序%d 时开始\n", t_start);

    sort(&para3);

    t_end=clock();//结束时刻
    printf("普通排序%d 时结束\n", t_end);
    printf("普通排序耗时:%d\n", t_end-t_start); //计算程序运行消耗的时间
}

void initElem(){
    srand((unsigned)time(NULL));
    int i;
    for(i=0;i<LENGTH;i++){
        elem[i]=rand()%MAX+1;
    }
}

/**
 * [sort description]
 * 一个简单的冒泡排序算法
 * @param para [description]
 */
void *sort(void * p){
    Para * para=(Para*)p;
    int i,j,temp;
    for(i=para->start;i<para->end;i++){
        for(j=para->end;j>i;j--){
            if(elem[j]<elem[j-1]){
                temp=elem[j];
                elem[j]=elem[j-1];
                elem[j-1]=temp;
            }
        }
    }
    if(para->end-para->start<LENGTH-1){ //如果是部分排序就认为是执行了多线程需要退出,否则不退出
        pthread_exit(0);
    }
}

void printElenm(int num[LENGTH]){
    int i;
    for(i=0;i<LENGTH;i++){
        printf("%d\n", num[i]);
    }
}

void merge(){
    int i=0,j=LENGTH/2+1,k=0;
    while(i<LENGTH/2+1&&j<LENGTH){
        if(elem[i]<elem[j]){
            res[k]=elem[i];
            k++;
            i++;
        }else{
            res[k]=elem[j];
            k++;
            j++;
        }
    }
    if(i<LENGTH/2){
        for(;i<LENGTH/2+1;i++,k++){
            res[k]=elem[i];
        }
    }else{
        for(;j<LENGTH;j++,k++){
            res[k]=elem[j];
        }
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值