Linux下多线程编程详解.docx

上传人:b****2 文档编号:2373648 上传时间:2023-05-03 格式:DOCX 页数:17 大小:18.95KB
下载 相关 举报
Linux下多线程编程详解.docx_第1页
第1页 / 共17页
Linux下多线程编程详解.docx_第2页
第2页 / 共17页
Linux下多线程编程详解.docx_第3页
第3页 / 共17页
Linux下多线程编程详解.docx_第4页
第4页 / 共17页
Linux下多线程编程详解.docx_第5页
第5页 / 共17页
Linux下多线程编程详解.docx_第6页
第6页 / 共17页
Linux下多线程编程详解.docx_第7页
第7页 / 共17页
Linux下多线程编程详解.docx_第8页
第8页 / 共17页
Linux下多线程编程详解.docx_第9页
第9页 / 共17页
Linux下多线程编程详解.docx_第10页
第10页 / 共17页
Linux下多线程编程详解.docx_第11页
第11页 / 共17页
Linux下多线程编程详解.docx_第12页
第12页 / 共17页
Linux下多线程编程详解.docx_第13页
第13页 / 共17页
Linux下多线程编程详解.docx_第14页
第14页 / 共17页
Linux下多线程编程详解.docx_第15页
第15页 / 共17页
Linux下多线程编程详解.docx_第16页
第16页 / 共17页
Linux下多线程编程详解.docx_第17页
第17页 / 共17页
亲,该文档总共17页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

Linux下多线程编程详解.docx

《Linux下多线程编程详解.docx》由会员分享,可在线阅读,更多相关《Linux下多线程编程详解.docx(17页珍藏版)》请在冰点文库上搜索。

Linux下多线程编程详解.docx

Linux下多线程编程详解

Linux下多线程编程详解

线程(thread)技术早在60年代就被提出,但真正应用多线程到操作系统中去,是在80年代中期,solaris是这方面的佼佼者。

传统的Unix也支持线程的概念,不过在一个进程(process)中只允许有一个线程,这样多线程就意味着多进程。

目前,多线程技术已被许多操作系统所支持,包括视窗系统/NT,当然,也包括Linux。

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

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

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

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

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

我们知道,在Linux系统下,启动一个新的进程必须分配给他独立的地址空间,建立众多的数据表来维护他的代码段、堆栈段和数据段,这是一种"昂贵"的多任务工作方式。

而运行于一个进程中的多个线程,他们彼此之间使用相同的地址空间,共享大部分数据,启动一个线程所花费的空间远远小于启动一个进程所花费的空间,而且,线程间彼此转换所需的时间也远远小于进程间转换所需要的时间。

据统计,总的说来,一个进程的开销大约是个线程开销的30倍左右,当然,在具体的系统上,这个数据可能会有较大的差别。

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

对不同进程来说,他们具有独立的数据空间,要进行数据的传递只能通过通信的方式进行,这种方式不仅费时,而且非常不方便。

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

当然,数据的共享也带来其他一些问题,有的变量不能同时被两个线程所修改,有的子程式中声明为static的数据更有可能给多线程程式带来灾难性的打击,这些正是编写多线程程式时最需要注意的地方。

  除了以上所说的好处外,不和进程比较,多线程程式作为一种多任务、并发的工作方式,当然有以下的好处:

  1)提高应用程式响应。

这对图像界面的程式尤其有意义,当一个操作耗时非常长时,整个系统都会等待这个操作,此时程式不会响应键盘、鼠标、菜单的操作,而使用多线程技术,将耗时长的操作(timeconsuming)置于一个新的线程,能避免这种尴尬的情况。

  2)使多CPU系统更加有效。

操作系统会确保当线程数不大于CPU数目时,不同的线程运行于不同的CPU上。

  3)改善程式结构。

一个既长又复杂的进程能考虑分为多个线程,成为几个独立或半独立的运行部分,这样的程式会利于理解和修改。

  下面我们先来尝试编写一个简单的多线程程式。

  简单的多线程编程

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

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

顺便说一下,Linux下pthread的实现是通过系统调用clone()来实现的。

clone()是Linux所特有的系统调用,他的使用方式类似fork,关于clone()的周详情况,有兴趣的读者能去查看有关文件说明。

下面我们展示一个最简单的多线程程式pthread_create.c。

一个重要的线程创建函数原型:

#include

intpthread_create(pthread_t*restricttidp,constpthread_attr_t*restrictattr,void*(*start_rtn)(void),void*restrictarg);

返回值:

若是成功建立线程返回0,否则返回错误的编号

形式参数:

pthread_t*restricttidp要创建的线程的线程id指针

constpthread_attr_t*restrictattr创建线程时的线程属性

void*(start_rtn)(void)返回值是void类型的指针函数

void*restrictargstart_rtn的行参

例程1:

功能:

创建一个简单的线程

程式名称:

pthread_create.c  

/********************************************************************************************

**Name:

pthread_create.c

**UsedtostudythemultithreadprogramminginLinuxOS

**Author:

zeickey

**Date:

2006/9/16

**Copyright(c)2006,AllRightsReserved!

*********************************************************************************************/

#include

#include

void*myThread1(void)

{

inti;

for(i=0;i

#include

#include

void*create(void*arg)

{

int*num;

num=(int*)arg;

printf("createparameteris%d\n",*num);

return(void*)0;

}

intmain(intargc,char*argv[])

{

pthread_ttidp;

interror;

inttest=4;

int*attr=&test;

error=pthread_create(&tidp,NULL,create,(void*)attr);

if(error)

{

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

return-1;

}

sleep

(1);

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

return0;

}

编译方法:

gcc-lpthreadpthread_int.c-Wall

执行结果:

createparameteris4

pthread_createiscreatediscreated...

例程总结:

能看出来,我们在main函数中传递的整行指针,传递到我们新建的线程函数中。

在上面的例子能看出来我们向新的线程传入了另一个线程的int数据,线程之间还能传递字符串或是更复杂的数据结构。

例程3:

程式功能:

向新建的线程传递字符串

程式名称:

pthread_string.c

/********************************************************************************************

**Name:

pthread_string.c

**UsedtostudythemultithreadprogramminginLinuxOS

**Passa‘char*‘parametertothethread.

**Author:

zeickey

**Date:

2006/9/16

**Copyright(c)2006,AllRightsReserved!

*********************************************************************************************/

#include

#include

#include

void*create(void*arg)

{

char*name;

name=(char*)arg;

printf("Theparameterpassedfrommainfunctionis%s\n",name);

return(void*)0;

}

intmain(intargc,char*argv[])

{

char*a="zieckey";

interror;

pthread_ttidp;

error=pthread_create(&tidp,NULL,create,(void*)a);

if(error!

=0)

{

printf("pthreadisnotcreated.\n");

return-1;

}

sleep

(1);

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

return0;

}

编译方法:

gcc-Wallpthread_string.c-lpthread

执行结果:

Theparameterpassedfrommainfunctioniszieckey

pthreadiscreated...

例程总结:

能看出来main函数中的字符串传入了新建的线程中。

例程4:

程式功能:

向新建的线程传递字符串

程式名称:

pthread_struct.c

/********************************************************************************************

**Name:

pthread_struct.c

**UsedtostudythemultithreadprogramminginLinuxOS

**Passa‘char*‘parametertothethread.

**Author:

zeickey

**Date:

2006/9/16

**Copyright(c)2006,AllRightsReserved!

*********************************************************************************************/

#include

#include

#include

#include

structmenber

{

inta;

char*s;

};

void*create(void*arg)

{

structmenber*temp;

temp=(structmenber*)arg;

printf("menber->a=%d\n",temp->a);

printf("menber->s=%s\n",temp->s);

return(void*)0;

}

intmain(intargc,char*argv[])

{

pthread_ttidp;

interror;

structmenber*b;

b=(structmenber*)malloc(sizeof(structmenber));

b->a=4;

b->s="zieckey";

error=pthread_create(&tidp,NULL,create,(void*)b);

if(error)

{

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

return-1;

}

sleep

(1);

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

return0;

}

编译方法:

gcc-Wallpthread_struct.c-lpthread

执行结果:

menber->a=4

menber->s=zieckey

pthreadiscreated...

例程总结:

能看出来main函数中的一个结构体传入了新建的线程中。

线程包含了标识进程内执行环境必须的信息。

他集成进程中的所有信息都是对线程进行共享的,包括文本程式、程式的全局内存和堆内存、栈及文件描述符。

例程5:

程式目的:

验证新建立的线程能共享进程中的数据

程式名称:

pthread_share.c

/********************************************************************************************

**Name:

pthread_share_data.c

**UsedtostudythemultithreadprogramminginLinuxOS

**Passa‘char*‘parametertothethread.

**Author:

zeickey

**Date:

2006/9/16

**Copyright(c)2006,AllRightsReserved!

*********************************************************************************************/

#include

#include

#include

staticinta=4;

void*create(void*arg)

{

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

printf("a=%d\n",a);

return(void*)0;

}

intmain(intargc,char*argv[])

{

pthread_ttidp;

interror;

a=5;

error=pthread_create(&tidp,NULL,create,NULL);

if(error!

=0)

{

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

return-1;

}

sleep

(1);

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

return0;

}

编译方法:

gcc-Wallpthread_share_data.c-lpthread

执行结果:

newpthread...

a=5

newthreadiscreated...

例程总结:

能看出来,我们在主线程(main函数)更改了我们的全局变量a的值的时候,我们新建立的线程则打印出来了改动的值,能看出能访问线程所在进程中的数据信息。

2、线程的终止

如果进程中所有一个线程中调用exit,_Exit,或是_exit,那么整个进程就会终止,

和此类似,如果信号的默认的动作是终止进程,那么,把该信号发送到线程会终止进程。

线程的正常退出的方式:

(1)线程只是从启动例程中返回,返回值是线程中的退出码

(2)线程能被另一个进程进行终止

(3)线程自己调用pthread_exit函数

两个重要的函数原型:

#include

voidpthread_exit(void*rval_ptr);

/*rval_ptr线程退出返回的指针*/

intpthread_join(pthread_tthread,void**rval_ptr);

/*成功结束进程为0,否则为错误编码*/

例程6

程式目的:

线程正常退出,接受线程退出的返回码

程式名称:

pthread_exit.c

/********************************************************************************************

**Name:

pthread_exit.c

**UsedtostudythemultithreadprogramminginLinuxOS

**Aexampleshowingathreadtoexitandwithareturncode.

**Author:

zeickey

**Date:

2006/9/16

**Copyright(c)2006,AllRightsReserved!

*********************************************************************************************/

#include

#include

#include

void*create(void*arg)

{

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

return(void*)8;

}

intmain(intargc,char*argv[])

{

pthread_ttid;

interror;

void*temp;

error=pthread_create(&tid,NULL,create,NULL);

if(error)

{

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

return-1;

}

error=pthread_join(tid,&temp);

if(error)

{

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

return-2;

}

printf("threadisexitcode%d\n",(int)temp);

return0;

}

编译方法:

gcc-Wallpthread_exit.c-lpthread

执行结果:

newthreadiscreated...

threadisexitcode8

例程总结:

能看出来,线程退出能返回线程的int数值。

线程退出不仅仅能返回线程的int数值,还能返回一个复杂的数据结构。

例程7

程式目的:

线程结束返回一个复杂的数据结构

程式名称:

pthread_return_struct.c

#include

#include

#include

structmenber

{

inta;

char*b;

}temp={8,"zieckey"};

void*create(void*arg)

{

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

return(void*)&temp;

}

intmain(intargc,char*argv[])

{

interror;

pthread_ttid;

structmenber*c;

error=pthread_create(&tid,NULL,create,NULL);

if(error)

{

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

return-1;

}

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

error=pthread_join(tid,(void*)&c);

if(error)

{

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

return-2;

}

printf("c->a=%d\n",c->a);

printf("c->b=%s\n",c->b);

sleep

(1);

return0;

}

编译方法:

gcc-Wallpthread_return_struct.c-lpthread

执行结果:

main...

newthread...

c->a=8

c->b=zieckey

例程总结:

一定要记得返回的数据结构要是在这个数据要返回的结构没有释放的时候应用,

如果数据结构已发生变化,那返回的就不会是我们所需要的,而是脏数据

3、线程标识

函数原型:

#include

pthread_tpthread_self(void);

pid_tgetpid(void);

getpid()用来取得目前进程的进程识别码,函数说明

例程8

程式目的:

实目前新建立的线程中打印该线程的id和进程id

程式名称:

pthread_id.c

/********************************************************************************************

**Name:

pthread_id.c

**UsedtostudythemultithreadprogramminginLinuxOS.

**Showinghowtogetthethread’stidandtheprocess’spid.

**Author:

zeickey

**Date:

2006/9/16

**Copyright(c)2006,AllRightsReserved!

*********************************************************************************************/

#include

#include

#include/*getpid()*/

void*create(void*arg)

{

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

printf("Thisthread’sidis%u\n",(unsignedint)pthread_self());

printf("Theprocesspidis%d\n",getpid());

return(void*)0;

}

intmain(intargc,char*argv[])

{

pthread_ttid;

interror;

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

error=pthread_create(&tid,NULL,create,NULL);

if(error)

{

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

return-1;

}

printf("Themainprocess’spidis%d\n",getpid());

sleep

(1);

return0;

}

编译方法:

gcc-Wall-lpthreadpthread_id.c

执行结果:

Mainthreadisstarting...

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

当前位置:首页 > 解决方案 > 学习计划

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

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