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

实验总结

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

精品资料

HostKvm($4.25/月),俄罗斯CN2带宽大升级,俄罗斯/香港高防限量5折优惠进行中

HostKvm是一家成立于2013年的国外VPS服务商,产品基于KVM架构,数据中心包括日本、新加坡、韩国、美国、俄罗斯、中国香港等多个地区机房,均为国内直连或优化线路,延迟较低,适合建站或者远程办公等。本月,商家旗下俄罗斯、新加坡、美国、香港等节点带宽进行了大幅度升级,俄罗斯机房国内电信/联通直连,CN2线路,150Mbps(原来30Mbps)带宽起,目前俄罗斯和香港高防节点5折骨折码继续优惠中...

Hostodo美国独立日优惠套餐年付13.99美元起,拉斯维加斯/迈阿密机房

Hostodo又发布了几款针对7月4日美国独立日的优惠套餐(Independence Day Super Sale),均为年付,基于KVM架构,采用NVMe硬盘,最低13.99美元起,可选拉斯维加斯或者迈阿密机房。这是一家成立于2014年的国外VPS主机商,主打低价VPS套餐且年付为主,基于OpenVZ和KVM架构,产品性能一般,支持使用PayPal或者支付宝等付款方式。商家客服响应也比较一般,推...

friendhosting:(优惠55%)大促销,全场VPS降价55%,9个机房,不限流量

每年的7月的最后一个周五是全球性质的“系统管理员日”,据说是为了感谢系统管理员的辛苦工作....friendhosting决定从现在开始一直到9月8日对其全球9个数据中心的VPS进行4.5折(优惠55%)大促销。所有VPS基于KVM虚拟,给100M带宽,不限制流量,允许自定义上传ISO...官方网站:https://friendhosting.net比特币、信用卡、PayPal、支付宝、微信、we...

linux多线程编程为你推荐
软银赛富李念老公是谁音乐播放器哪个好最好的音乐播放器下载录音软件哪个好什么录音软件最好用苹果手机助手哪个好苹果手机助手哪个好用些谁知道车险哪个好买汽车保险,买哪几种比较好红茶和绿茶哪个好红茶好还是绿茶好?美国国际东西方大学明尼苏达大学(是莫瑞斯分校)和美国东北大学 应该去哪一个 是这个方面的专家回答啊!有偏见性的不要说!美国国际东西方大学美国新常春藤大学有哪些?google广告申请谷歌广告怎么申请?qq网盘在哪里QQ网盘在哪里
上海vps 服务器配置技术网 国外服务器 美国主机论坛 permitrootlogin 免费博客空间 php空间申请 工作站服务器 域名和空间 免费网络 lamp怎么读 cdn网站加速 深圳域名 镇江高防 服务器托管价格 移动王卡 accountsuspended 架设代理服务器 删除域名 美国服务器 更多