多线程排序-v1

源码

// 拆分数据使用多线程-V11.c
#include <stdio.h>
#include <pthread.h>
#include <time.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <stdbool.h>

#define SIZE 16

// 原始数据结构体
struct size_data
{
    int size;
    int *data;
};

// 多线程缓存的数据结构体
struct data_info
{
    int size;
    int *data;
};

// 多线程结构体
struct thread_info
{
    struct size_data array;
    struct data_info *bins;
};

// 多线程互斥锁
pthread_mutex_t lock;

// 分配内存空间
int *allocate(int size)
{
    int *space;
    space = (int *)calloc(size, sizeof(int));
    if (space == NULL)
    {
        perror("Error allocate");
        exit(EXIT_FAILURE);
    }
    return space;
}

// 生成随机数据
void produce_data(struct size_data array)
{
    srand(1);
    for (int i = 0; i < array.size; i++)
    {
        array.data[i] = rand() % 1000;
    }
}

// 打印数据
void print_data(struct size_data array, char * txt)
{
    FILE *fp;
    char num_str[4] = {0};

    fp = fopen(txt, "w");
    if (fp == NULL)
    {
        perror("Error print data");
        exit(EXIT_FAILURE);
    }

    for (int i = 0; i < array.size; i++)
    {
        sprintf(num_str, "%d", array.data[i]);
        fwrite(num_str, sizeof(num_str), 1, fp);
        fputc('\n', fp);
    }

    fclose(fp);
}

// 划分数据给各个线程
void *split_data(void *param)
{
    struct thread_info args = *(struct thread_info *)param;
    struct size_data array = args.array;
    struct data_info * bins = args.bins;

    pthread_mutex_lock(&lock);

    for (int i = 0; i < array.size; i++)
    {
        int number = array.data[i];
        if (number < 250)
        {
            bins[0].data[bins[0].size++] = number;
        }
        else if (number < 500)
        {
            bins[1].data[bins[1].size++] = number;
        }
        else if (number < 750)
        {
            bins[2].data[bins[2].size++] = number;
        }
        else
        {
            bins[3].data[bins[3].size++] = number;
        }
    }

    pthread_mutex_unlock(&lock);
    printf("over thread ID:%d.\n", pthread_self());
}

// 排序算法
void insertion(struct data_info bin)
{
    for (int i = 1; i < bin.size; i++)
    {
        for (int j = i; j > 0; j--)
        {
            if (bin.data[j - 1] > bin.data[j])
            {
                int temp;
                temp = bin.data[j];
                bin.data[j] = bin.data[j - 1];
                bin.data[j - 1] = temp;
            }
            else
            {
                break;
            }
        }
    }
}

// 将数据从线程缓存区复制到原始数据区
void move_back(struct size_data array, struct data_info bins[])
{
    for (int bin = 0; bin < 4; bin++)
    {
        for (int i = 0; i < bins[bin].size; i++)
        {
            *array.data++ = bins[bin].data[i];
        }
    }
}

// 判断是否排序正确
bool is_sorted(struct size_data array)
{
    bool sorted = true;
    for (int i = 0; i < array.size - 1; i++)
    {
        if (array.data[i] > array.data[i + 1])
            sorted = false;
    }
    return sorted;
}
// 主函数
int main(int argc, char * argv[])
{
    // 初始化参数
    struct size_data array;
    struct data_info bins[4];
    struct thread_info threads[4];
    pthread_t thread_type[4];

    // 根据输入参数,设置数据量级
    if (argc < 2)
    {
        array.size = SIZE;
    }
    else 
    {
        array.size = pow(2, atoi(argv[1]));
    }

    // 分配内存空间
    array.data = allocate(array.size);
    for (int i = 0; i < 4; i++)
    {
        bins[i].size = 0;
        bins[i].data = allocate(array.size);    // 为什么用array.size?
    }
    
    // 随机生成数据
    produce_data(array);
    
    // 打印数据
    print_data(array, "orignal.txt");
    
    // 分配多线程任务
    int *start_data = array.data;
    pthread_mutex_init(&lock, NULL);

    for (int i = 0; i < 4; i++)
    {
        threads[i].array.size = array.size / 4;
        threads[i].array.data = start_data;
        start_data += array.size / 4;
        threads[i].bins = bins;
        if (pthread_create(&thread_type[i], NULL, split_data, (void *)&threads[i]))
        {
            perror("Error creating thread.\n");
            exit(EXIT_FAILURE);
        }
    }

    // 多线程同步
    for (int i = 0; i < 4; i++)
    {
        pthread_join(thread_type[i], NULL); // 不能加&,会卡主
    }

    // 销毁线程同步锁
    pthread_mutex_destroy(&lock);
    
    // 计算各个线程数据量的总数
    int sum = 0;
    for (int i = 0; i < 4; i++)
    {
        sum += bins[i].size;
    }
    printf("Total size:%d.\n", sum);
    
    // 合并排序
    for (int i = 0; i < 4; i++)
    {
        insertion(bins[i]);
    }
    
    // 数据从线程缓存,复制到原始数组内存空间
    move_back(array, bins);

    // 打印数据
    print_data(array, "insertion.txt");
    
    // 判断是否排序完成
    printf(is_sorted(array) ? "sorted\n":"not sorted\n");

    // 释放内存空间
    free(array.data);
    for (int i = 0; i < 4; i++)
    {
        free(bins[i].data); // 这个内存空间的作用是?
    }
    
    exit(EXIT_SUCCESS);
}

makefile

v11:v11.o 
	gcc -o v11 v11.o -lm -lpthread
v11.0:v11.c
	gcc -c v11.c
.PHONY:clean
clean:
	-rm *.o
	-rm v11
	-rm *.txt
posted @ 2022-07-05 15:50  starc的miao  阅读(47)  评论(0)    收藏  举报