实验七Linux多线程编程实验报告.docx
《实验七Linux多线程编程实验报告.docx》由会员分享,可在线阅读,更多相关《实验七Linux多线程编程实验报告.docx(11页珍藏版)》请在冰点文库上搜索。
![实验七Linux多线程编程实验报告.docx](https://file1.bingdoc.com/fileroot1/2023-7/14/10d038e8-97a5-467b-929f-7881865c6c9c/10d038e8-97a5-467b-929f-7881865c6c9c1.gif)
实验七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、完成教材上多线程试验试验内容。
并分析程序实施结果。
试验总结:
由运行结果能够看出,创建线程、释放资源根据次序,而每个线程运行和结束是独立与并行。