线程实验七: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、 完成教材上多线程实验的实验内容。并分析程序的执行结果。精品资料

实验总结

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

精品资料

A400互联37.8元/季,香港节点cn2,cmi线路云服务器,1核/1G/10M/300G

A400互联怎么样?A400互联是一家成立于2020年的商家,A400互联是云服务器网(yuntue.com)首次发布的云主机商家。本次A400互联给大家带来的是,全新上线的香港节点,cmi+cn2线路,全场香港产品7折优惠,优惠码0711,A400互联,只为给你提供更快,更稳,更实惠的套餐,香港节点上线cn2+cmi线路云服务器,37.8元/季/1H/1G/10M/300G,云上日子,你我共享。...

hosteons:10Gbps带宽,免费Windows授权,自定义上传ISO,VPS低至$21/年,可选洛杉矶达拉斯纽约

hosteons当前对美国洛杉矶、达拉斯、纽约数据中心的VPS进行特别的促销活动:(1)免费从1Gbps升级到10Gbps带宽,(2)Free Blesta License授权,(3)Windows server 2019授权,要求从2G内存起,而且是年付。 官方网站:https://www.hosteons.com 使用优惠码:zhujicepingEDDB10G,可以获得: 免费升级10...

ZJI:韩国BGP+CN2线路服务器,国内三网访问速度优秀,8折优惠码每月实付440元起

zji怎么样?zji最近新上韩国BGP+CN2线路服务器,国内三网访问速度优秀,适用8折优惠码zji,优惠后韩国服务器最低每月440元起。zji主机支持安装Linux或者Windows操作系统,会员中心集成电源管理功能,8折优惠码为终身折扣,续费同价,全场适用。ZJI是原Wordpress圈知名主机商:维翔主机,成立于2011年,2018年9月启用新域名ZJI,提供中国香港、台湾、日本、美国独立服...

linux多线程编程为你推荐
软银孙正义马云富还是孙正义富杀毒软件哪个好杀毒软件哪个最好迈腾和帕萨特哪个好新帕萨特和新迈腾哪个好?华为p40和mate30哪个好华为p40手机。跟荣耀30哪个好?少儿英语哪个好少儿英语哪个好网页传奇哪个好玩哪个传奇类网页游戏即好玩又不花钱??海克斯皮肤哪个好摄魂使者薇恩和海克斯安妮皮肤哪个好 怎么合成牡丹江教育云空间登录云空间怎么登入牡丹江教育云空间登录请问一下校园云空间的登录方式有哪些?上海dns服务器地址谁知道上海移动无线网卡的DNS服务器地址
虚拟主机试用 阿云浏览器 80vps 百度云100as 香港托管 远程登陆工具 最好看的qq空间 ibrs 免费ftp空间申请 免费网站申请 新天域互联 cdn联盟 腾讯实名认证中心 亚马逊香港官网 华为云服务登录 google台湾 路由跟踪 免费asp空间申请 工信部网站备案查询 贵阳电信 更多