实验七Linux多线程编程实验报告.docx

上传人:b****0 文档编号:17103721 上传时间:2023-07-22 格式:DOCX 页数:12 大小:18.33KB
下载 相关 举报
实验七Linux多线程编程实验报告.docx_第1页
第1页 / 共12页
实验七Linux多线程编程实验报告.docx_第2页
第2页 / 共12页
实验七Linux多线程编程实验报告.docx_第3页
第3页 / 共12页
实验七Linux多线程编程实验报告.docx_第4页
第4页 / 共12页
实验七Linux多线程编程实验报告.docx_第5页
第5页 / 共12页
实验七Linux多线程编程实验报告.docx_第6页
第6页 / 共12页
实验七Linux多线程编程实验报告.docx_第7页
第7页 / 共12页
实验七Linux多线程编程实验报告.docx_第8页
第8页 / 共12页
实验七Linux多线程编程实验报告.docx_第9页
第9页 / 共12页
实验七Linux多线程编程实验报告.docx_第10页
第10页 / 共12页
实验七Linux多线程编程实验报告.docx_第11页
第11页 / 共12页
实验七Linux多线程编程实验报告.docx_第12页
第12页 / 共12页
亲,该文档总共12页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

实验七Linux多线程编程实验报告.docx

《实验七Linux多线程编程实验报告.docx》由会员分享,可在线阅读,更多相关《实验七Linux多线程编程实验报告.docx(12页珍藏版)》请在冰点文库上搜索。

实验七Linux多线程编程实验报告.docx

实验七Linux多线程编程实验报告

实验七:

Linux多线程编程(4课时)

实验目的:

掌握线程的概念;熟悉Linux下线程程序编译的过程;掌握多线程程序编写方法。

实验原理:

为什么有了进程的概念后,还要再引入线程呢?

使用多线程到底有哪些好处?

什么的系统应该选用多线程?

我们首先必须回答这些问题。

1多线程概念

使用多线程的理由之一是和进程相比,它是一种非常"节俭"的多任务操作方式。

运行于一个进程中的多个线程,它们彼此之间使用相同的地址空间,共享大部分数据,启动一个线程所花费的空间远远小于启动一个进程所花费的空间。

使用多线程的理由之二是线程间方便的通信机制。

同一进程下的线程之间共享数据空间,所以一个线程的数据可以直接为其它线程所用,这不仅快捷,而且方便。

2多线程编程函数

Linux系统下的多线程遵循POSIX线程接口,称为pthread。

编写Linux下的多线程程序,需要使用头文件pthread.h,连接时需要使用库libpthread.a。

pthread_t在头文件/usr/include/bits/pthreadtypes.h中定义:

typedefunsignedlongintpthread_t;它是一个线程的标识符。

函数pthread_create用来创建一个线程,它的原型为:

externintpthread_create((pthread_t*thread,constpthread_attr_t*attr,

void*(*start_routine)(void*),void*arg));

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

函数pthread_join用来等待一个线程的结束。

函数原型为:

externintpthread_join(pthread_tth,void**thread_return);

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

函数pthread_exit的函数原型为:

externvoidpthread_exit(void*retval);

唯一的参数是函数的返回代码,只要pthread_join中的第二个参数thread_return不是NULL,这个值将被传递给thread_return。

3修改线程的属性

线程属性结构为pthread_attr_t,它在头文件/usr/include/pthread.h中定义。

属性值不能直接设置,须使用相关函数进行操作,初始化的函数为pthread_attr_init,这个函数必须在pthread_create函数之前调用。

设置线程绑定状态的函数为pthread_attr_setscope,它有两个参数,第一个是指向属性结构的指针,第二个是绑定类型,它有两个取值:

PTHREAD_SCOPE_SYSTEM(绑定的)和PTHREAD_SCOPE_PROCESS(非绑定的)。

另外一个可能常用的属性是线程的优先级,它存放在结构sched_param中。

用函数pthread_attr_getschedparam和函数pthread_attr_setschedparam进行存放,一般说来,我们总是先取优先级,对取得的值修改后再存放回去。

4线程的数据处理

和进程相比,线程的最大优点之一是数据的共享性,各个进程共享父进程处沿袭的数据段,可以方便的获得、修改数据。

但这也给多线程编程带来了许多问题。

我们必须当心有多个不同的进程访问相同的变量。

许多函数是不可重入的,即同时不能运行一个函数的多个拷贝(除非使用不同的数据段)。

在函数中声明的静态变量常常带来问题,函数的返回值也会有问题。

互斥锁

互斥锁用来保证一段时间内只有一个线程在执行一段代码。

必要性显而易见:

假设各个线程向同一个文件顺序写入数据,最后得到的结果一定是灾难性的。

条件变量

互斥锁一个明显的缺点是它只有两种状态:

锁定和非锁定。

而条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足,它常和互斥锁一起使用。

使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程往往解开相应的互斥锁并等待条件发生变化。

信号量

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

信号量本质上是一个非负的整数计数器,它被用来控制对公共资源的访问。

当公共资源增加时,调用函数sem_post()增加信号量。

只有当信号量值大于0时,才能使用公共资源,使用后,函数sem_wait()减少信号量。

函数sem_trywait()和函数pthread_mutex_trylock()起同样的作用,它是函数sem_wait()的非阻塞版本。

实验内容:

线程函数编译时需要添加特殊编译选项:

gcc*.c-lpthread-o

1、完成教材上thread.c的例子,想一下每次执行时结果相同吗,为什么?

答:

每个线程的运行和结束时无序的、独立与并行的。

实验代码:

/*thread.c*/

#include

#include

#include

#defineTHREAD_NUMBER3/*线程数*/

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

#defineDELAY_TIME_LEVELS6.0/*小任务之间的最大时间间隔*/

void*thrd_func(void*arg)//指针好乱,这里看不懂定义了什么,求解释

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

{/*线程函数例程*/

intthrd_num=(int)arg;//这个是赋值吗?

看不懂,求解释

//定义了一个整型参数,取值为arg

intdelay_time=0;

intcount=0;

printf("Thread%disstarting\n",thrd_num);

for(count=0;count

{

delay_time=(int)(rand()*DELAY_TIME_LEVELS/(RAND_MAX))+1;

printf("\tThread%d:

job%ddelay=%d\n",thrd_num,count,delay_time);

sleep(delay_time);//暂停?

秒//暂停随机秒

}

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

//输出格式:

Threadthrd_num:

jobcountdelay=delay_time回车

printf("Thread%dfinished\n",thrd_num);

//输出格式:

Threadthrd_numfinished回车

pthread_exit(NULL);

}

intmain(void)

{

pthread_tthread[THREAD_NUMBER];

//定义了一个类型为pthread_t的数组,数组元素的个数为3

intno=0,res;

void*thrd_ret;//这句什么意思?

求解释

//定义了一个指针,指向哪里后面的程序里有。

srand(time(NULL));//这句什么意思?

求解释

//用系统时间计算一个随机数。

for(no=0;no

{

/*创建多线程*/

res=pthread_create(&thread[no],NULL,thrd_func,(void*)no);//&thread[no]线程标识符

//pthread_create函数的参数含义请看书。

if(res!

=0)//创建线程出错时res=错误码

{

printf("Createthread%dfailed\n",no);

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

}

}

printf("Createtreadssuccess\nWaitingforthreadstofinish...\n");

//如果上面没退出进程,则创建线程成功

for(no=0;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()函数执行成功。

{

printf("Thread%djoined\n",no);

}

else

{

printf("Thread%djoinfailed\n",no);

}

}

return0;

}

2、完成教材上thread_mutex.c例,查看运行情况。

和上例比较有何不同,想一下为什么会出现这种差异?

答:

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

#include

#include

#include

#defineTHREAD_NUM3/*线程数*/

#defineREPEAT_NUM3/*每个线程的小任务数*/

#defineDELAY_TIME_LEVELS6.0/*小任务之间的最大时间间隔*/

pthread_mutex_tmutex;

void*thrd_func(void*arg)

{

intthrd_num=(int)arg;

intdelay_time=0,count=0;

intres;

/*互斥锁上锁*/

res=pthread_mutex_lock(&mutex);

if(res)

{

printf("Thread%dlockfailed\n",thrd_num);

pthread_exit(NULL);

}

printf("Thread%disstarting\n",thrd_num);

for(count=0;count

{

delay_time=(int)(rand()*DELAY_TIME_LEVELS/(RAND_MAX))+1;

sleep(delay_time);

printf("\tThread%d:

job%ddelay=%d\n",thrd_num,count,delay_time);

}

printf("Thread%dfinished\n",thrd_num);

pthread_mutex_unlock(&mutex);

pthread_exit(NULL);

}

intmain(void){

pthread_tthread[THREAD_NUM];

intno=0,res;

void*thrd_ret;

srand(time(NULL));

/*互斥锁初始化*/

pthread_mutex_init(&mutex,NULL);

for(no=0;no

{

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

if(res!

=0)

{

printf("Createthread%dfailed\n",no);

exit(res);

}

}

printf("Createtreadssuccess\nWaitingforthreadstofinish...\n");

for(no=0;no

{

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

if(!

res)

{

printf("Thread%djoined\n",no);

}

else

{

printf("Thread%djoinfailed\n",no);

}

}

pthread_mutex_destroy(&mutex);

return0;

}

 

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

答:

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

程序代码:

#include

#include

#include

#defineREPEAT_NUMBER3/*线程中的小任务数*/

#defineDELAY_TIME_LEVELS10.0/*小任务之间的最大时间间隔*/

intfinish_flag=0;

void*thrd_func(void*arg)

{

intdelay_time=0;

intcount=0;

printf("Threadisstarting\n");

for(count=0;count

{

delay_time=(int)(rand()*DELAY_TIME_LEVELS/(RAND_MAX))+1;

sleep(delay_time);

printf("\tThread:

job%ddelay=%d\n",count,delay_time);

}

printf("Threadfinished\n");

finish_flag=1;

pthread_exit(NULL);

}

intmain(void)

{

pthread_tthread;

pthread_attr_tattr;

intno=0,res;

void*thrd_ret;

srand(time(NULL));

/*初始化线程属性对象*/

res=pthread_attr_init(&attr);

if(res!

=0)

{

printf("Createattributefailed\n");

exit(res);

}

/*设置线程绑定属性*/

res=pthread_attr_setscope(&attr,PTHREAD_SCOPE_SYSTEM);

/*设置线程分离属性*/

res+=pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);

if(res!

=0)

{

printf("Settingattributefailed\n");

exit(res);

}

res=pthread_create(&thread,&attr,thrd_func,NULL);

if(res!

=0)

{

printf("Createthreadfailed\n");

exit(res);

}

/*释放线程属性对象*/

pthread_attr_destroy(&attr);

printf("Createtreadsuccess\n");

while(!

finish_flag)

{

printf("Waitingforthreadtofinish...\n");

sleep

(2);

}

return0;

}

 

4、完成教材上多线程实验的实验内容。

并分析程序的执行结果。

 

实验总结:

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

 

WelcomeTo

Download!

!

!

 

欢迎您的下载,资料仅供参考!

 

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 经管营销 > 经济市场

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2