线程实验七:linux多线程编程(实验报告)

linux多线程编程  时间:2021-01-19  阅读:()

实验七 Linux多线程编程4课时

实验目的掌握线程的概念熟悉Linux下线程程序编译的过程掌握多线程程序编写方法。

实验原理为什么有了进程的概念后还要再引入线程呢使用多线程到底有哪些好处什么的系统应该选用多线程我们首先必须回答这些问题。

1多线程概念

使用多线程的理由之一是和进程相比它是一种非常"节俭"的多任务操作方式。运行于一个进程中的多个线程它们彼此之间使用相同的地址空间共享大部分数据启动一个线程所花费的空间远远小于启动一个进程所花费的空间。使用多线程的理由之二是线程间方便的通信机制。同一进程下的线程之间共享数据空间所以一个线程的数据可以直接为其它线程所用这不仅快捷而且方便。2多线程编程函数

Linux系统下的多线程遵循POSIX线程接口称为pthread。编写Linux下的多线程程序需要使用头文件pthread.h 连接时需要使用库l ibpthread.a。pthread_t在头文件/usr/include/bits/pthreadtypes.h中定义typedef unsigned long int pthread_t;它是一个线程的标识符。

函数p th re a d_c re a te用来创建一个线程它的原型为extern int pthread_create((pthread_t *thread,const pthread_attr_t *attr,void*(*start_routine) (void*),void*arg));

第一个参数为指向线程标识符的指针第二个参数用来设置线程属性第三个参数是线程运行函数的起始地址最后一个参数是运行函数的参数。

函数pthread_join用来等待一个线程的结束。函数原型为

精品资料

extern int pthread_jo in(pthread_t th,vo id**thread_return);

第一个参数为被等待的线程标识符第二个参数为一个用户定义的指针它可以用来存储被等待线程的返回值。

函数pthread_exit的函数原型为extern void pthread_exit(vo id*retval);

唯一的参数是函数的返回代码只要pth read_join中的第二个参数thread_retu rn 不是N U LL 这个值将被传递给thread_return。

3修改线程的属性

线程属性结构为pthread_attr_t 它在头文件/usr/include/pthread.h中定义。属性值不能直接设置须使用相关函数进行操作初始化的函数为pthread_attr_in it 这个函数必须在p th re a d_c re a te函数之前调用。

设置线程绑定状态的函数为pth read_attr_setscope 它有两个参数第一个是指向属性结构的指针 第二个是绑定类型 它有两个取值PTHREAD_SCOPE_SYSTEM绑定的和PTHREAD_SCOPE_PROCESS非绑定的。

另外一个可能常用的属性是线程的优先级它存放在结构sched_param中。用函数pthread_attr_getschedparam和函数pthread_attr_setschedparam进行存放一般说来我们总是先取优先级对取得的值修改后再存放回去。

4线程的数据处理

和进程相比线程的最大优点之一是数据的共享性各个进程共享父进程处沿袭的数据段可以方便的获得、修改数据。但这也给多线程编程带来了许多问题。我们必须当心有多个不同的进程访问相同的变量。许多函数是不可重入的即同

精品资料

时不能运行一个函数的多个拷贝除非使用不同的数据段。在函数中声明的静态变量常常带来问题函数的返回值也会有问题。

互斥锁

互斥锁用来保证一段时间内只有一个线程在执行一段代码。必要性显而易见假设各个线程向同一个文件顺序写入数据最后得到的结果一定是灾难性的。条件变量

互斥锁一个明显的缺点是它只有两种状态锁定和非锁定。而条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足它常和互斥锁一起使用。使用时条件变量被用来阻塞一个线程当条件不满足时线程往往解开相应的互斥锁并等待条件发生变化。

信号量

信号量既可以作为二值计数器(即0,1),也可以作为资源计数器.

信号量本质上是一个非负的整数计数器它被用来控制对公共资源的访问。当公共资源增加时调用函数sem_post 增加信号量。只有当信号量值大于时才能使用公共资源使用后函数sem_wait  减少信号量。函数sem_trywait  和函数pthread_mutex_trylock 起同样的作用它是函数sem_wait  的非阻塞版本。

实验内容线程函数编译时需要添加特殊编译选项 gcc *.c-lp th read-o

1 、 完成教材上th read.c的例子想一下每次执行时结果相同吗为什么答每个线程的运行和结束时无序的、独立与并行的。

实验代码

精品资料

/* thread c*/

#include<stdio h>

#include<stdl ib h>

#include<pthread h>

#define THREAD_NUMBER3/*线程数*/

#define REPEAT_NUMBER5/*每个线程中的小任务数*/

#define DELAY_TIME_LEVELS60/*小任务之间的最大时间间隔*/void*thrd_func(void*arg) //指针好乱这里看不懂定义了什么求解释

//定义了一个返回值为指向空类型的指针的函数该函数的参数为一个指针

{ /*线程函数例程*/intthrd_num=(int)arg; //这个是赋值吗看不懂求解释

//定义了一个整型参数取值为arg intdelay_time=0;intcount=0;printf("Thread%d is starting\n", thrd_num);for (count=0;count<REPEAT_NUMBER;count++)

{delay_time=(int)(rand() *DELAY_TIME_LEVELS/(RAND_MAX))+ 1 ;pri ntf("\tThread%d: job%d delay=%d\n",thrd_num,count,delay_ti me);sleep(delay_time); //暂停秒//暂停随机秒

}

//\t输出一个Tab占8列

//输出格式  Thread thrd_num: job countdelay=delay_time 回车pri ntf("Th read%d fin i shed\n", th rd_num);

//输出格式 Thread thrd_num finished 回车pthread_exit(NULL);

}int main(void)

{pthread_t thread[THREAD_NUMBER];

//定义了一个类型为pthread_t的数组数组元素的个数为3intno=0, res;void* thrd_ret; //这句什么意思求解释

//定义了一个指针指向哪里后面的程序里有。srand(time(NULL)); //这句什么意思求解释

//用系统时间计算一个随机数。for (no=0;no<THREAD_NUMBER; no++)

{

/*创建多线程*/res=pthread_create(&thread[no],NULL, thrd_func, (void*)no); //&thread[no]线程标识符//pthread_create函数的参数含义请看书。if (res!=0) //创建线程出错时res=错误码

{printf("Create thread%d fai led\n",no);

精品资料

exit(res);//上面的不是退出进程而是判断pthread_create 函数是否成功执行。

}

}printf("Create treads success\n Waiting for threads to finish \n");

//如果上面没退出进程则创建线程成功for (no=0;no<THREAD_NUMBER; no++)

{

/*等待线程结束*/res=pthread_join(thread[no],&thrd_ret);

// thread[no]线程标识符此例总共有thread[0]  thread[1]  thread[2]  3个线程//请看书上pthread_join  函数的参数含义。if (!res) //res=0时挂起线程成功

//res=0时说明pthread_join  函数执行成功。

{pri ntf("Th read%d j oin ed\n", no);

}else

{pri ntf("Thread%d join fai l ed\n",no);

}

}return 0;

}

2、 完成教材上th read_m utex.c例查看运行情况。和上例比较有何不同想一下为什么会出现这种差异

答这里3个线程之间的运行顺序跟创建线程的顺序相同。

#include<stdio h>

#include<stdlib h>

#include<pthread h>

#define THREAD_NUM 3/*线程数*/

#define REPEAT_NUM 3/*每个线程的小任务数*/

#define DELAY_TIME_LEVELS 60/*小任务之间的最大时间间隔*/pthread_mutex_t mutex;void*thrd_func(void*arg)

{int thrd_num=(int)arg;int delay_time=0,count=0;int res;

/*互斥锁上锁*/

精品资料

res=pthread_mutex_lock(&mutex);if(res)

{printf("Thread%d lock failed\n", thrd_num);pthread_exit(NULL);

}printf("Thread%d is starting\n", thrd_num);for(count=0;count<REPEAT_NUM;count++)

{delay_time=(int)(rand() *DELAY_TIME_LEVELS/(RAND_MAX))+1;sleep(delay_time);printf("\tThread%d: job%d delay=%d\n",thrd_num,count,delay_time);}printf("Thread%d finished\n", thrd_num);pthread_mutex_unlock(&mutex);pthread_exit(NULL);

}int main(void) {pthread_t thread[THREAD_NUM];int no=0, res;void*thrd_ret;srand(time(NULL));

/*互斥锁初始化*/pthread_mutex_init(&mutex,NULL);for (no=0; no<THREAD_NUM;no++)

{res=pthread_create(&thread[no],NULL, thrd_func, (void*)no);if(res !=0)

{printf("Create thread%d failed\n",no);exit(res);

}

}printf("Create treads success\n Waiting for threads tofinish \n");for(no=0;no<THREAD_NUM;no++)

{res=pthread_join(thread[no],&thrd_ret);if(!res)

{printf("Thread%d joined\n",no);

}

精品资料

else

{printf("Thread%d join failed\n",no);

}

}pthread_mutex_destroy(&mutex);return 0;

}

3、 完成教材上th read_attr.c例子并运行查看结果然后和前面两个例子比较查看系统资源的差异。

答理论中线程在运行结束后就回收系统资源并释放内存。

程序代码

#include<stdio h>

#include<stdlib h>

#include<pthread h>

#define REPEAT_NUMBER 3/*线程中的小任务数*/

#define DELAY_TIME_LEVELS 100/*小任务之间的最大时间间隔*/int finish_flag=0;void*thrd_func(void*arg)

{int delay_time=0;int count=0;printf("Thread is starting\n");for (count=0;count<REPEAT_NUMBER;count++)

{delay_time=(int)(rand() *DELAY_TIME_LEVELS/(RAND_MAX))+1;sleep(delay_time);printf("\tThread: job%d delay=%d\n",count,delay_time);

}printf("Thread finished\n");f inish_flag=1;pthread_exit(NULL);

}int main(void)

{pthread_t thread;pthread_attr_t attr;

精品资料

int no=0, res;void*thrd_ret;srand(time(NULL));

/*初始化线程属性对象*/res=pthread_attr_init(&attr);if(res !=0)

{printf("Create attribute failed\n");exit(res);

}

/*设置线程绑定属性*/res=pthread_attr_setscope(&attr,PTHREAD_SCOPE_SYSTEM);

/*设置线程分离属性*/res+=pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACH ED);if(res !=0)

{printf("Setting attribute failed\n");exit(res);

}res=pthread_create(&thread,&attr, thrd_func,NULL);if(res !=0)

{printf("Create thread failed\n");exit(res);

}

/*释放线程属性对象*/pthread_attr_destroy(&attr);printf("Create tread success\n");whi le(!finish_flag)

{printf("Waiting for thread to finish \n");sleep(2);

}return 0;

}

4、 完成教材上多线程实验的实验内容。并分析程序的执行结果。精品资料

实验总结

由运行结果可以看出创建线程、释放资源按照顺序而每个线程的运行和结束是独立与并行的。

精品资料

云如故枣庄高防(49元)大内存2H2G49元8H8G109元

云如故是一家成立于2018年的国内企业IDC服务商,由山东云如故网络科技有限公司运营,IDC ICP ISP CDN VPN IRCS等证件齐全!合法运营销售,主要从事自营高防独立服务器、物理机、VPS、云服务器,虚拟主机等产品销售,适合高防稳定等需求的用户,可用于建站、游戏、商城、steam、APP、小程序、软件、资料存储等等各种个人及企业级用途。机房可封UDP 海外 支持策略定制 双层硬件(傲...

DiyVM:499元/月香港沙田服务器,L5630*2/16G内存/120G SSD硬盘/5M CN2线路

DiyVM是一家成立于2009年的国人主机商,提供的产品包括VPS主机、独立服务器租用等,产品数据中心包括中国香港、日本大阪和美国洛杉矶等,其中VPS主机基于XEN架构,支持异地备份与自定义镜像,VPS和独立服务器均可提供内网IP功能。商家VPS主机均2GB内存起步,三个地区机房可选,使用优惠码后每月69元起;独立服务器开设在香港沙田电信机房,CN2线路,自动化开通上架,最低499元/月起。下面以...

古德云香港cn2/美国cn235元/月起, gia云服务器,2核2G,40G系统盘+50G数据盘

古德云(goodkvm)怎么样?古德云是一家成立于2020年的商家,原名(锤子云),古德云主要出售VPS服务器、独立服务器。古德云主打产品是香港cn2弹性云及美西cn2云服务器,采用的是kvm虚拟化构架,硬盘Raid10。目前,古德云香港沙田cn2机房及美国五星级机房云服务器,2核2G,40G系统盘+50G数据盘,仅35元/月起,性价比较高,可以入手!点击进入:古德云goodkvm官方网站地址古德...

linux多线程编程为你推荐
聚酯纤维和棉哪个好聚酯纤维棉和羽丝绵哪个好涡轮增压和自然吸气哪个好发动机涡轮增压好还是自然吸气好dnf魔枪士转职哪个好DNF魔枪士转职转哪个好 决战者征战者转职云盘哪个好哪个网盘好用 而且下载速度快 还免费willyunlee求几近完美演员表,几近完美女主角几近完美男主角是谁?dns服务器地址如何知道自己的IP地址和DNS服务器地址?360云存储360云盘最高多少内存360云u盘360云u盘无法连接怎么回事?强生美瞳月抛强生美瞳月抛有8.8基弧么什么快递最便宜寄大物件什么快递便宜
vps优惠码cnyvps 域名备案网站 企业域名备案 fdcservers 新加坡服务器 ssh帐号 商务主机 可外链相册 河南移动网 t云 优酷黄金会员账号共享 360云服务 服务器论坛 ledlamp 登陆qq空间 北京主机托管 学生机 phpwind论坛 日本小学生 tko 更多