操作系统实验——浅谈pthread库线程创建

来源:互联网 发布:nat123端口映 编辑:程序博客网 时间:2024/06/01 10:12

初学操作系统对于线程的知识了解是很重要的,因此我们借用对pthread库函数的一些小运用来加深对多线程的认识。
注:本实验在linux系统下进行。

“pthread.h”头文件无法在windows平台下直接引用,需要在编译器编译过程中自行添加,笔者测试用的是pthreads-w32-2-4-0-release.exe,有兴趣的读者可自行研究这里不作扩展。


涉及到的函数有:

pthread_create //用于创建一个新的线程

//pthread_create函数原型:#include <pthread.h> int pthread_create(pthread_t *restrict tidp,               const pthread_attr_t *restrict attr,               void *(*start_rtn)(void),               void *restrict arg); Returns: 0 if OK, error number on failure
  • pthread_t *restrict tidp ,tidp是指向一个线程ID的指针。
  • const pthread_attr_t *restrict attr:线程属性设置。
  • void *(*start_rtn)(void),第三个参数是一个指向函数指针,即线程运行函数的起始地址。新创建的线程从该函数的起始地址开始运行。
  • void *restrict arg:给执行函数传递参数参数
    返回值:
    若成功则返回0,否则返回出错编号。

由 restrict修饰的指针是最初唯一对指针所指向的对象进行存取的方法,所有修改该指针所指向内存中内容的操作都必须通过该指针来修改,而不能通过其它途径(其它变量或指针)来修改,保证了代码的安全性。

pthread_jion//阻塞,等待线程结束

//pthread_jion函数原型#include <pthread.h>int pthread_join(pthread_t thread,               void **retval); Returns: 0 if OK, error number on failure

-pthread_t thread:线程ID。
-void **retval为一个用户定义的指针,它可以用来存储被等待线程的返回值。
返回值:
若成功则返回0,否则返回出错编号。

当我们需要所有线程都结束之后再对他们的结果进行统一操作时,就需要在主函数里加入阻塞函数,等待所有线程都结束后在进行后续操作。


实例:随机生成10万个浮点数,创建4个线程分别实现2.5万个浮点数之和最后完成10万个浮点数之和。比较多线程和单线程的计算时间。

#include <stdio.h>#include <stdlib.h>#include <time.h>#include <pthread.h>#include <memory.h>#include <sys/time.h>#define Max_Set 100000float ssum[Max_Set];pthread_t thread[4];float suma=0.0;float sumb=0.0;float sumc=0.0;float sumd=0.0;float sum=0.0;void fullssum(float a[],int length){    for(int i=0;i<length;i++)    ssum[i]=rand()/(float)(RAND_MAX/10);}void *thread_a(void *in){    printf("i am thread_a\n");    for(int i=0;i<Max_Set/4;i++)    {        suma+=ssum[i];    }    printf("suma=====%f\n",suma);    pthread_exit((void *)0);}void *thread_b(void *in){    printf("i am thread_b\n");    for(int i=Max_Set/4;i<Max_Set/2;i++)        {                sumb+=ssum[i];        }        printf("sumb=====%f\n",sumb);    pthread_exit((void *)0);}void *thread_c(void *in){        printf("i am thread_c\n");        for(int i=Max_Set/2;i<Max_Set*3/4;i++)        {                sumc+=ssum[i];        }        printf("sumc=====%f\n",sumc);        pthread_exit((void *)0);}void *thread_d(void *in){        printf("i am thread_d\n");        for(int i=Max_Set*3/4;i<Max_Set;i++)        {                sumd+=ssum[i];        }        printf("sumd=====%f\n",sumd);        pthread_exit((void *)0);}int main(){    int temp;    struct timeval start, end1,end2;    //用随机数填满数组    fullssum(ssum,Max_Set);    //初始化线程ID    memset(&thread ,0 ,sizeof(thread));    //获取当前时间    gettimeofday(&start,NULL);    if((temp=pthread_create(&thread[0],NULL,thread_a,NULL))!=0)    printf("error in thread_a\n");    else    printf("thread_a creat success!\n");    if((temp=pthread_create(&thread[1],NULL,thread_b,NULL))!=0)        printf("error in thread_b\n");    else        printf("thread_b creat success!\n");     if((temp=pthread_create(&thread[2],NULL,thread_c,NULL))!=0)        printf("error in thread_c\n");     else        printf("thread_c creat success!\n");     if((temp=pthread_create(&thread[3],NULL,thread_d,NULL))!=0)        printf("error in thread_d\n");     else        printf("thread_d creat success!\n");    for(int i=0;i<4;i++)    {        if(thread[0]!=0)        {           pthread_join(thread[0],NULL);        printf("thread%d come to an end\n",i+1);        }    }    //等待所有线程结束计算和    printf("RESULT1=======%f\n",suma+sumb+sumc+sumd);    //获取当前时间    gettimeofday(&end1,NULL);    int time1=1000000*(end1.tv_sec-start.tv_sec)+end1.tv_usec-start.tv_usec;    //输出多线程计算用时    printf("time1======%d\n",time1);    for(int j=0;j<Max_Set;j++)    {        sum+=ssum[j];    }    printf("RESULT2=======%f\n",sum);    gettimeofday(&end2,NULL);    int time2=1000000*(end2.tv_sec-end1.tv_sec)+end2.tv_usec-end1.tv_usec;    //输出单线程计算用时    printf("time2======%d\n",time2);}

使用gcc编译pthread库程序需要加 -lpthread
例如:gcc pthread.c -o thread -lpthread

0 0
原创粉丝点击