http://blog.csdn.net/ruglcc/article/details/7874076
zieckey?
(
zieckey
@
yahoo.com.cn
)
?? ?
線程(
thread
)技術(shù)早在
60
年代就被提出,但真正應(yīng)用多線程到操作系統(tǒng)中去,是在
80
年代中期,
solaris
是這方面的佼佼者。傳統(tǒng)的
Unix
也支持線程的概念,但是在一個(gè)進(jìn)程(
process
)中只允許有一個(gè)線程,這樣多線程就意味著多進(jìn)程。
現(xiàn)在,多線程技術(shù)已經(jīng)被許多操作系統(tǒng)所支持,包括
Windows/NT
,當(dāng)然,也包括
Linux
。
為什么有了進(jìn)程的概念后,還要再引入線程呢?使用多線程到底有哪些好處?什么的系統(tǒng)應(yīng)該選用多線程?我們首先必須回答這些問題。
使用多線程的理由之一是和進(jìn)程相比,它是一種非常
"
節(jié)儉
"
的多任務(wù)操作方式。我們知道,在
Linux
系統(tǒng)下,啟動(dòng)一個(gè)新的進(jìn)程必須分配給它獨(dú)立的地址空間,建立眾多的數(shù)據(jù)表來維護(hù)它的代碼段、堆棧段和數(shù)據(jù)段,這是一種
"
昂貴
"
的多任務(wù)工作方式。而運(yùn)行于一個(gè)進(jìn)程中的多個(gè)線程,它們彼此之間使用相同的地址空間,共享大部分?jǐn)?shù)據(jù),啟動(dòng)一個(gè)線程所花費(fèi)的空間遠(yuǎn)遠(yuǎn)小于啟動(dòng)一個(gè)進(jìn)程所花費(fèi)的空間,而且,線程間彼此切換所需的時(shí)間也遠(yuǎn)遠(yuǎn)小于進(jìn)程間切換所需要的時(shí)間。據(jù)統(tǒng)計(jì),總的說來,一個(gè)進(jìn)程的開銷大約是一個(gè)線程開銷的
30
倍左右,當(dāng)然,在具體的系統(tǒng)上,這個(gè)數(shù)據(jù)可能會(huì)有較大的區(qū)別。
使用多線程的理由之二是線程間方便的通信機(jī)制。對不同進(jìn)程來說,它們具有獨(dú)立的數(shù)據(jù)空間,要進(jìn)行數(shù)據(jù)的傳遞只能通過通信的方式進(jìn)行,這種方式不僅費(fèi)時(shí),而且很不方便。線程則不然,由于同一進(jìn)程下的線程之間共享數(shù)據(jù)空間,所以一個(gè)線程的數(shù)據(jù)可以直接為其它線程所用,這不僅快捷,而且方便。當(dāng)然,數(shù)據(jù)的共享也帶來其他一些問題,有的變量不能同時(shí)被兩個(gè)線程所修改,有的子程序中聲明為
static
的數(shù)據(jù)更有可能給多線程程序帶來災(zāi)難性的打擊,這些正是編寫多線程程序時(shí)最需要注意的地方。
除了以上所說的優(yōu)點(diǎn)外,不和進(jìn)程比較,多線程程序作為一種多任務(wù)、并發(fā)的工作方式,當(dāng)然有以下的優(yōu)點(diǎn):
1)?
提高應(yīng)用程序響應(yīng)。這對圖形界面的程序尤其有意義,當(dāng)一個(gè)操作耗時(shí)很長時(shí),整個(gè)系統(tǒng)都會(huì)等待這個(gè)操作,此時(shí)程序不會(huì)響應(yīng)鍵盤、鼠標(biāo)、菜單的操作,而使用多線程技術(shù),將耗時(shí)長的操作(
time consuming
)置于一個(gè)新的線程,可以避免這種尷尬的情況。
2)?
使多
CPU
系統(tǒng)更加有效。操作系統(tǒng)會(huì)保證當(dāng)線程數(shù)不大于
CPU
數(shù)目時(shí),不同的線程運(yùn)行于不同的
CPU
上。
3)?
改善程序結(jié)構(gòu)。一個(gè)既長又復(fù)雜的進(jìn)程可以考慮分為多個(gè)線程,成為幾個(gè)獨(dú)立或半獨(dú)立的運(yùn)行部分,這樣的程序會(huì)利于理解和修改。
下面我們先來嘗試編寫一個(gè)簡單的多線程程序。
簡單的多線程編程
Linux
系統(tǒng)下的多線程遵循
POSIX
線程接口,稱為
pthread
。編寫
Linux
下的多線程程序,需要使用頭文件
pthread.h
,連接時(shí)需要使用庫
libpthread.a
。順便說一下,
Linux
下
pthread
的實(shí)現(xiàn)是通過系統(tǒng)調(diào)用
clone
()來實(shí)現(xiàn)的。
clone
()是
Linux
所特有的系統(tǒng)調(diào)用,它的使用方式類似
fork
,關(guān)于
clone
()的詳細(xì)情況,有興趣的讀者可以去查看有關(guān)文檔說明。下面我們展示一個(gè)最簡單的多線程程序
pthread_create.c
。
一個(gè)重要的線程創(chuàng)建函數(shù)原型:
#include <pthread.h>
int pthread_create(pthread_t *restrict tidp,const pthread_attr_t *restrict attr, void *(*start_rtn)(void),void *restrict arg);
????
返回值:若是成功建立線程返回
0,
否則返回錯(cuò)誤的編號(hào)
????
形式參數(shù):
??????????????? pthread_t *restrict tidp?
要?jiǎng)?chuàng)建的線程的線程
id
指針
??????????????? const pthread_attr_t *restrict attr?
創(chuàng)建線程時(shí)的線程屬性
??????????????? void* (start_rtn)(void)?
返回值是
void
類型的指針函數(shù)
??????????????? void *restrict arg?? start_rtn
的行參
?????????????? ?
例程
1
:
????????????????????????????????
????
功能:創(chuàng)建一個(gè)簡單的線程
????
程序名稱:
pthread_create.c???????
- /******************************************************************************************** ?
- **????Name:pthread_create.c ?
- **????Used?to?study?the?multithread?programming?in?Linux?OS ?
- **????Author:zeickey ?
- **????Date:2006/9/16???????? ?
- **????Copyright?(c)?2006,All?Rights?Reserved! ?
- *********************************************************************************************/ ??
- ??
- #include?<stdio.h> ??
- #include?<pthread.h> ??
- ??
- void ?*myThread1( void )??
- {??
- ???? int ?i;??
- ???? for ?(i=0;?i<100;?i++)??
- ????{??
- ????????printf( "This?is?the?1st?pthread,created?by?zieckey./n" );??
- ????????sleep(1); //Let?this?thread?to?sleep?1?second,and?then?continue?to?run ??
- ????}??
- }??
- ??
- void ?*myThread2( void )??
- {??
- ???? int ?i;??
- ???? for ?(i=0;?i<100;?i++)??
- ????{??
- ????????printf( "This?is?the?2st?pthread,created?by?zieckey./n" );??
- ????????sleep(1);??
- ????}??
- }??
- ??
- int ?main()??
- {??
- ???? int ?i=0,?ret=0;??
- ????pthread_t?id1,id2;??
- ??????
- ????ret?=?pthread_create(&id2,?NULL,?( void *)myThread1,?NULL);??
- ???? if ?(ret)??
- ????{??
- ????????printf( "Create?pthread?error!/n" );??
- ???????? return ?1;??
- ????}??
- ??????
- ????ret?=?pthread_create(&id2,?NULL,?( void *)myThread2,?NULL);??
- ???? if ?(ret)??
- ????{??
- ????????printf( "Create?pthread?error!/n" );??
- ???????? return ?1;??
- ????}??
- ??????
- ????pthread_join(id1,?NULL);??
- ????pthread_join(id2,?NULL);??
- ??????
- ???? return ?0;??
- }??
我們編譯此程序:
# gcc pthread_create.c -lpthread
因?yàn)?
pthread
的庫不是
linux
系統(tǒng)的庫,所以在進(jìn)行編譯的時(shí)候要加上
-lpthread
,否則編譯不過,會(huì)出現(xiàn)下面錯(cuò)誤
thread_test.c:?
在函數(shù)
?‘create’?
中:
thread_test.c:7:?
警告:
?
在有返回值的函數(shù)中,程序流程到達(dá)函數(shù)尾
/tmp/ccOBJmuD.o: In function `main':thread_test.c:(.text+0x4f)
:對
‘pthread_create’
未定義的引用
collect2: ld?
返回
?1
運(yùn)行,我們得到如下結(jié)果:
# ./a.out?
This is the 1st pthread,created by zieckey.
This is the 2st pthread,created by zieckey.
This is the 1st pthread,created by zieckey.
This is the 2st pthread,created by zieckey.
This is the 2st pthread,created by zieckey.
This is the 1st pthread,created by zieckey.
....
兩個(gè)線程交替執(zhí)行。
此例子介紹了創(chuàng)建線程的方法。
下面例子介紹向線程傳遞參數(shù)。
例程
2
:
????
功能:向新的線程傳遞整形值
????
程序名稱:
pthread_int.c
- /******************************************************************************************** ?
- **????Name:pthread_int.c ?
- **????Used?to?study?the?multithread?programming?in?Linux?OS ?
- **????Pass?a?parameter?to?the?thread. ?
- **????Author:zeickey ?
- **????Date:2006/9/16???????? ?
- **????Copyright?(c)?2006,All?Rights?Reserved! ?
- *********************************************************************************************/ ??
- ??
- #include?<stdio.h> ??
- #include?<pthread.h> ??
- #include?<unistd.h> ??
- ??
- void ?*create( void ?*arg)??
- {??
- ???? int ?*num;??
- ????num=( int ?*)arg;??
- ????printf( "create?parameter?is?%d?/n" ,*num);??
- ???? return ?( void ?*)0;??
- }??
- int ?main( int ?argc?, char ?*argv[])??
- {??
- ????pthread_t?tidp;??
- ???? int ?error;??
- ??????
- ???? int ?test=4;??
- ???? int ?*attr=&test;??
- ??????
- ????error=pthread_create(&tidp,NULL,create,( void ?*)attr);??
- ??
- ???? if (error)??
- ????????{??
- ????????printf( "pthread_create?is?created?is?not?created?...?/n" );??
- ???????? return ?-1;??
- ????????}??
- ????sleep(1);??
- ????printf( "pthread_create?is?created?.../n" );??
- ???? return ?0;??????????
- }??
????
編譯方法:
gcc -lpthread pthread_int.c -Wall
????
執(zhí)行結(jié)果:
create parameter is 4
pthread_create is created is? created ...
????
例程總結(jié):
????
可以看出來,我們在
main
函數(shù)中傳遞的整行指針,傳遞到我們新建的線程函數(shù)中。
????
在上面的例子可以看出來我們向新的線程傳入了另一個(gè)線程的
int
數(shù)據(jù),線程之間還可以傳遞字符串或是更復(fù)雜的數(shù)據(jù)結(jié)構(gòu)。
例程
3
:
????
程序功能:向新建的線程傳遞字符串
??? ????
程序名稱:
pthread_string.c
- /******************************************************************************************** ?
- **????Name:pthread_string.c ?
- **????Used?to?study?the?multithread?programming?in?Linux?OS ?
- **????Pass?a?‘char*‘?parameter?to?the?thread. ?
- **????Author:zeickey ?
- **????Date:2006/9/16???????? ?
- **????Copyright?(c)?2006,All?Rights?Reserved! ?
- *********************************************************************************************/ ??
- #include?<pthread.h> ??
- #include?<stdio.h> ??
- #include?<unistd.h> ??
- ??
- void ?*create( void ?*arg)??
- {??
- ???? char ?*name;??
- ????name=( char ?*)arg;??
- ????printf( "The?parameter?passed?from?main?function?is?%s??/n" ,name);??
- ???? return ?( void ?*)0;??
- }??
- ??
- int ?main( int ?argc,? char ?*argv[])??
- {??
- ???? char ?*a= "zieckey" ;??
- ???? int ?error;??
- ????pthread_t?tidp;??
- ??
- ????error=pthread_create(&tidp,?NULL,?create,?( void ?*)a);??
- ??
- ???? if (error!=0)??
- ????{??
- ????????printf( "pthread?is?not?created./n" );??
- ???????? return ?-1;??
- ????}??
- ????sleep(1);??
- ????printf( "pthread?is?created...?/n" );??
- ???? return ?0;??
- }????
??
??
編譯方法:
gcc -Wall pthread_string.c -lpthread
????
執(zhí)行結(jié)果:
The parameter passed from main function is zieckey??
pthread is created...?
????
例程總結(jié):
????
可以看出來
main
函數(shù)中的字符串傳入了新建的線程中。
例程
4
:
????
程序功能:向新建的線程傳遞字符串
??? ????
程序名稱:
pthread_struct.c
- /******************************************************************************************** ?
- **????Name:pthread_struct.c ?
- **????Used?to?study?the?multithread?programming?in?Linux?OS ?
- **????Pass?a?‘char*‘?parameter?to?the?thread. ?
- **????Author:zeickey ?
- **????Date:2006/9/16???????? ?
- **????Copyright?(c)?2006,All?Rights?Reserved! ?
- *********************************************************************************************/ ??
- #include?<stdio.h> ??
- #include?<pthread.h> ??
- #include?<unistd.h> ??
- #include?<stdlib.h> ??
- ??
- struct ?menber??
- {??
- ???? int ?a;??
- ???? char ?*s;??
- };??
- ??
- void ?*create( void ?*arg)??
- {??
- ???? struct ?menber?*temp;??
- ????temp=( struct ?menber?*)arg;??
- ????printf( "menber->a?=?%d??/n" ,temp->a);??
- ????printf( "menber->s?=?%s??/n" ,temp->s);??
- ???? return ?( void ?*)0;??
- }??
- ??
- int ?main( int ?argc, char ?*argv[])??
- {??
- ????pthread_t?tidp;??
- ???? int ?error;??
- ???? struct ?menber?*b;??
- ????b=( struct ?menber?*)malloc(? sizeof ( struct ?menber)?);??
- ????b->a?=?4;??
- ????b->s?=? "zieckey" ;??
- ??
- ????error?=?pthread_create(&tidp,?NULL,?create,?( void ?*)b);??
- ??
- ???? if (?error?)??
- ????{??
- ????????printf( "phread?is?not?created.../n" );??
- ???????? return ?-1;??
- ????}??
- ????sleep(1);??
- ????printf( "pthread?is?created.../n" );??
- ???? return ?0;??
- }??
??
編譯方法:
gcc -Wall pthread_struct.c -lpthread
????
執(zhí)行結(jié)果:
menber->a = 4??
menber->s = zieckey??
pthread is created...
????
例程總結(jié):
????
可以看出來
main
函數(shù)中的一個(gè)結(jié)構(gòu)體傳入了新建的線程中。
????
線程包含了標(biāo)識(shí)進(jìn)程內(nèi)執(zhí)行環(huán)境必須的信息。他集成了進(jìn)程中的所有信息都是對線程進(jìn)行共享的,包括文本程序、程序的全局內(nèi)存和堆內(nèi)存、棧以及文件描述符。
????
例程
5
:
????
程序目的:驗(yàn)證新建立的線程可以共享進(jìn)程中的數(shù)據(jù)
????
程序名稱:
pthread_share.c??
- /******************************************************************************************** ?
- **????Name:pthread_share_data.c ?
- **????Used?to?study?the?multithread?programming?in?Linux?OS ?
- **????Pass?a?‘char*‘?parameter?to?the?thread. ?
- **????Author:zeickey ?
- **????Date:2006/9/16???????? ?
- **????Copyright?(c)?2006,All?Rights?Reserved! ?
- *********************************************************************************************/ ??
- #include?<stdio.h> ??
- #include?<pthread.h> ??
- #include?<unistd.h> ??
- ??
- static ? int ?a=4;??
- void ?*create( void ?*arg)??
- {??
- ????printf( "new?pthread?...?/n" );??
- ????printf( "a=%d??/n" ,a);??
- ???? return ?( void ?*)0;??
- }??
- ??
- int ?main( int ?argc, char ?*argv[])??
- {??
- ????pthread_t?tidp;??
- ???? int ?error;??
- ??????
- ????a=5;??
- ??
- ????error=pthread_create(&tidp,?NULL,?create,?NULL);??
- ??
- ???? if (error!=0)??
- ????{??
- ????????printf( "new?thread?is?not?create?...?/n" );??
- ???????? return ?-1;??
- ????}??
- ??????
- ????sleep(1);??
- ??????
- ????printf( "new?thread?is?created?...?/n" );??
- ???? return ?0;??
- }??
? ??
??
編譯方法:
gcc -Wall pthread_share_data.c -lpthread
????
執(zhí)行結(jié)果:
new pthread ...?
a=5??
new thread is created ...?
? ??
例程總結(jié):
可以看出來,我們在主線程更改了我們的全局變量
a
的值的時(shí)候,我們新建立的線程則打印出來了改變的值,可以看出可以訪問線程所在進(jìn)程中的數(shù)據(jù)信息
2
、線程的終止
????
如果進(jìn)程中任何一個(gè)線程中調(diào)用
exit
,
_Exit,
或者是
_exit
,那么整個(gè)進(jìn)程就會(huì)終止,
????
與此類似,如果信號(hào)的默認(rèn)的動(dòng)作是終止進(jìn)程,那么,把該信號(hào)發(fā)送到線程會(huì)終止進(jìn)程。
????
線程的正常退出的方式:
?????? (1)?
線程只是從啟動(dòng)例程中返回,返回值是線程中的退出碼
?????? (2)?
線程可以被另一個(gè)進(jìn)程進(jìn)行終止
?????? (3)?
線程自己調(diào)用
pthread_exit
函數(shù)
????
兩個(gè)重要的函數(shù)原型:
#include <pthread.h>
void pthread_exit(void *rval_ptr);
/*rval_ptr?
線程退出返回的指針
*/
int pthread_join(pthread_t thread,void **rval_ptr);
?? /*
成功結(jié)束進(jìn)程為
0,
否則為錯(cuò)誤編碼
*/
????
例程
6
????
程序目的:線程正常退出,接受線程退出的返回碼
????
程序名稱:
pthread_exit.c
- /******************************************************************************************** ?
- **????Name:pthread_exit.c ?
- **????Used?to?study?the?multithread?programming?in?Linux?OS ?
- **????A?example?showing?a?thread?to?exit?and?with?a?return?code. ?
- **????Author:zeickey ?
- **????Date:2006/9/16???????? ?
- **????Copyright?(c)?2006,All?Rights?Reserved! ?
- *********************************************************************************************/ ??
- ??
- #include?<stdio.h> ??
- #include?<pthread.h> ??
- #include?<unistd.h> ??
- ??
- void ?*create( void ?*arg)??
- {??
- ????printf( "new?thread?is?created?...?/n" );??
- ???? return ?( void ?*)8;??
- }??
- ??
- int ?main( int ?argc, char ?*argv[])??
- {??
- ????pthread_t?tid;??
- ???? int ?error;??
- ???? void ?*temp;??
- ??
- ????error?=?pthread_create(&tid,?NULL,?create,?NULL);??
- ??
- ???? if (?error?)??
- ????{??
- ????????printf( "thread?is?not?created?...?/n" );??
- ???????? return ?-1;??
- ????}??
- ????error?=?pthread_join(tid,?&temp);??
- ??
- ???? if (?error?)??
- ????{??
- ????????printf( "thread?is?not?exit?...?/n" );??
- ???????? return ?-2;??
- ????}??
- ??????
- ????printf( "thread?is?exit?code?%d?/n" ,?( int ?)temp);??
- ???? return ?0;??
- }??
??
編譯方法:
gcc -Wall pthread_exit.c -lpthread
????
執(zhí)行結(jié)果:
new thread is created ...
thread is exit code 8
????
例程總結(jié):
可以看出來,線程退出可以返回線程的
int
數(shù)值。線程退出不僅僅可以返回線程的
int
數(shù)值,還可以返回一個(gè)復(fù)雜的數(shù)據(jù)結(jié)構(gòu)。
????
例程
7
????
程序目的:線程結(jié)束返回一個(gè)復(fù)雜的數(shù)據(jù)結(jié)構(gòu)
????
程序名稱:
pthread_return_struct.c
- #include?<stdio.h> ??
- #include?<pthread.h> ??
- #include?<unistd.h> ??
- ??
- struct ?menber??
- {??
- ???? int ?a;??
- ???? char ?*b;??
- }temp={8, "zieckey" };??
- void ?*create( void ?*arg)??
- {??
- ????printf( "new?thread?...?/n" );??
- ???? return ?( void ?*)&temp;??
- }??
- ??
- int ?main( int ?argc, char ?*argv[])??
- {??
- ???? int ?error;??
- ????pthread_t?tid;??
- ???? struct ?menber?*c;??
- ??
- ????error?=?pthread_create(&tid,?NULL,?create,?NULL);??
- ??????
- ???? if (?error?)??
- ????{??
- ????????printf( "new?thread?is?not?created?...?/n" );??
- ???????? return ?-1;??
- ????}??
- ????printf( "main?...?/n" );??
- ??
- ????error?=?pthread_join(tid,( void ?*)&c);??
- ??
- ???? if (?error?)??
- ????{??
- ????????printf( "new?thread?is?not?exit?...?/n" );??
- ???????? return ?-2;??
- ????}??
- ????printf( "c->a?=?%d??/n" ,c->a);??
- ????printf( "c->b?=?%s??/n" ,c->b);??
- ????sleep(1);??
- ???? return ?0;??
- }??
??
編譯方法:
gcc -Wall pthread_return_struct.c -lpthread
????
執(zhí)行結(jié)果:
main ...
new thread ...
c->a = 8
c->b = zieckey
例程總結(jié):
一定要記得返回的數(shù)據(jù)結(jié)構(gòu)要是在這個(gè)數(shù)據(jù)要返回的結(jié)構(gòu)沒有釋放的時(shí)候應(yīng)用,
如果數(shù)據(jù)結(jié)構(gòu)已經(jīng)發(fā)生變化,那返回的就不會(huì)是我們所需要的,而是臟數(shù)據(jù)
3
、線程標(biāo)識(shí)
????
函數(shù)原型:
? ?
#include <pthread.h>
pthread_t pthread_self(void);
pid_t getpid(void);
??? getpid()
用來取得目前進(jìn)程的進(jìn)程識(shí)別碼
,
函數(shù)說明
????
例程
8
????
程序目的:實(shí)現(xiàn)在新建立的線程中打印該線程的
id
和進(jìn)程
id
????
程序名稱:
pthread_id.c
???
- /******************************************************************************************** ?
- **????Name:pthread_id.c ?
- **????Used?to?study?the?multithread?programming?in?Linux?OS. ?
- **????Showing?how?to?get?the?thread's?tid?and?the?process's?pid. ?
- **????Author:zeickey ?
- **????Date:2006/9/16???????? ?
- **????Copyright?(c)?2006,All?Rights?Reserved! ?
- *********************************************************************************************/ ??
- #include?<stdio.h> ??
- #include?<pthread.h> ??
- #include?<unistd.h>?/*getpid()*/ ??
- ??
- void ?*create( void ?*arg)??
- {??
- ????printf( "New?thread?....?/n" );??
- ????printf( "This?thread's?id?is?%u??/n" ,?(unsigned? int )pthread_self());??
- ????printf( "The?process?pid?is?%d??/n" ,getpid());??
- ???? return ?( void ?*)0;??
- }???
- ??
- int ?main( int ?argc, char ?*argv[])??
- {??
- ????pthread_t?tid;??
- ???? int ?error;??
- ??
- ????printf( "Main?thread?is?starting?...?/n" );??
- ??
- ????error?=?pthread_create(&tid,?NULL,?create,?NULL);??
- ??
- ???? if (error)??
- ????{??
- ????????printf( "thread?is?not?created?...?/n" );??
- ???????? return ?-1;??
- ????}??
- ????printf( "The?main?process's?pid?is?%d??/n" ,getpid());??
- ????sleep(1);??
- ???? return ?0;??
- }??
????
編譯方法:
???
gcc -Wall -lpthread pthread_id.c
????
執(zhí)行結(jié)果:
Main thread is starting ...?
The main process's pid is 3307??
New thread ....?
This thread's id is 3086347152??
The process pid is 3307?
函數(shù)原型:
? ?#include <pthread.h>
void pthread_cleanup_push(void (*rtn)(void *),void *arg);
????
函數(shù)
rtn
是清理函數(shù),
arg
是調(diào)用參數(shù)
void pthread_cleanup_pop(int execute);
??
? ??
在前面講過線程的終止方式,是正常終止還是非正常終止,都會(huì)存在一個(gè)資源釋放的問題,在
posix
中提供了一組,就是我們上面看的函數(shù)進(jìn)行線程退出的處理函數(shù),有些像在進(jìn)程中的
atexit
函數(shù)。釋放的方式是指
pthread_cleanup_push
的調(diào)用點(diǎn)到
pthread_cleanup_pop
之間程序段進(jìn)行終止。
??? pthread_cleanup_push()/pthread_cleanup_pop
采用先入后出的方式的棧的管理方式,
void *rtn(void *),
在執(zhí)行
pthread_cleanup_push()
時(shí)壓入函數(shù)棧,多次執(zhí)行
pthread_cleanup_push()
形成一個(gè)函數(shù)鏈,在執(zhí)行這個(gè)函數(shù)鏈的時(shí)候會(huì)以反方向彈出,即先入后出。
execute
參數(shù)表識(shí),是否執(zhí)行彈出清理函數(shù),當(dāng)
execute=0
時(shí)不進(jìn)行彈出清理函數(shù),非零的時(shí)候彈出處理函數(shù)。
????
例程
9
????
程序目的:實(shí)現(xiàn)在正常結(jié)束線程的時(shí)候,進(jìn)行函數(shù)處理
????
程序名稱:
pthread_clean.c
?
- /******************************************************************************************** ?
- **????Name:pthread_clean.c ?
- **????Used?to?study?the?multithread?programming?in?Linux?OS ?
- **????A?example?showing?a?thread?to?be?cleaned. ?
- **????Author:zeickey ?
- **????Date:2008/6/28???????? ?
- **????Copyright?(c)?2006,All?Rights?Reserved! ?
- *********************************************************************************************/ ??
- #include?<stdio.h> ??
- #include?<pthread.h> ??
- #include?<unistd.h> ??
- void ?*clean( void ?*arg)??
- {??
- ????printf( "cleanup?:%s??/n" ,( char ?*)arg);??
- ???? return ?( void ?*)0;??
- }??
- void ?*thr_fn1( void ?*arg)??
- {??
- ????printf( "thread?1?start??/n" );??
- ????pthread_cleanup_push(?( void *)clean, "thread?1?first?handler" );??
- ????pthread_cleanup_push(?( void *)clean, "thread?1?second?hadler" );??
- ????printf( "thread?1?push?complete??/n" );??
- ???? if (arg)??
- ????{??
- ???????? return (( void ?*)1);??
- ????}??
- ????pthread_cleanup_pop(0);??
- ????pthread_cleanup_pop(0);??
- ???? return ?( void ?*)1;??
- }??
- void ?*thr_fn2( void ?*arg)??
- {??
- ????printf( "thread?2?start??/n" );??
- ????pthread_cleanup_push(?( void *)clean, "thread?2?first?handler" );??
- ????pthread_cleanup_push(?( void *)clean, "thread?2?second?handler" );??
- ????printf( "thread?2?push?complete??/n" );??
- ???? if (arg)??
- ????{??
- ????????pthread_exit(( void ?*)2);??
- ????}??
- ????pthread_cleanup_pop(0);??
- ????pthread_cleanup_pop(0);??
- ????pthread_exit(( void ?*)2);??
- }??
- int ?main( void )??
- {??
- ???? int ?err;??
- ????pthread_t?tid1,tid2;??
- ???? void ?*tret;??
- ??
- ????err=pthread_create(&tid1,NULL,thr_fn1,( void ?*)1);??
- ???? if (err!=0)??
- ????{??
- ????????printf( "error?....?/n" );??
- ???????? return ?-1;??
- ????}??
- ????err=pthread_create(&tid2,NULL,thr_fn2,( void ?*)1);??
- ??
- ???? if (err!=0)??
- ????{??
- ????????printf( "error?....?/n" );??
- ???????? return ?-1;??
- ????}??
- ????err=pthread_join(tid1,&tret);??
- ???? if (err!=0)??
- ????{??
- ????????printf( "error?....?/n" );??
- ???????? return ?-1;??
- ????}??
- ????printf( "thread?1?exit?code?%d??/n" ,( int )tret);??
- ??
- ????err=pthread_join(tid2,&tret);??
- ???? if (err!=0)??
- ????{??
- ????????printf( "error?....?" );??
- ???????? return ?-1;??
- ????}??
- ??
- ????printf( "thread?2?exit?code?%d??/n" ,( int )tret);??
- ??????
- ???? return ?1;??
- }??
????
編譯方法:
?gcc -Wall -lpthread pthread_clean.c
????
執(zhí)行結(jié)果:
thread 1 start??
thread 1 push complete??
thread 1 exit code 1??
thread 2 start??
thread 2 push complete??
cleanup :thread 2 second handler??
cleanup :thread 2 first handler??
thread 2 exit code 2?
pthread_join
? ?
SYNOPSIS
? ? ? ?#include <pthread.h>
? ? ? ?int pthread_join(pthread_t thread, void **rval_ptr);
DESCRIPTION
? ? ? ?The ?pthread_join() ?function shall suspend execution of the calling thread until the target thread terminates, unless the target thread has already termi-nated. On return from a successful pthread_join() call with a non-NULL value_ptr argument, the value passed to pthread_exit() ?by ?the ?terminating ?thread shall ?be ?made ?available ?in the location referenced by rval_ptr. When a pthread_join() returns successfully, the target thread has been terminated. The results of multiple simultaneous calls to pthread_join() specifying the same target thread are undefined. If the thread calling pthread_join() is canceled, then the target thread shall not be detached.
pthread_join用于掛起當(dāng)前線程(調(diào)用pthread_join的線程),直到thread指定的線程終止運(yùn)行為止,當(dāng)前線程才繼續(xù)執(zhí)行。thread指定的線程的返回值由rval_ptr返回。一個(gè)線程所使用的資源在對該線程調(diào)用pthread_join之前不會(huì)被重新分配,因此對于每個(gè)切入的線程必須調(diào)用一次pthread_join函數(shù)。線程必須可切入的而不是處于被分離狀態(tài),并且其他線程不能對同一線程再次應(yīng)用pthread_join調(diào)用。通過pthread_create調(diào)用中使用一個(gè)適當(dāng)?shù)腶ttr參數(shù)或者調(diào)用pthread_detach可以讓一個(gè)線程處于被分離狀態(tài)。
? ?
SYNOPSIS
? ? ? ?#include <pthread.h>
? ? ? ?int pthread_join(pthread_t thread, void **rval_ptr);
DESCRIPTION
? ? ? ?The ?pthread_join() ?function shall suspend execution of the calling thread until the target thread terminates, unless the target thread has already termi-nated. On return from a successful pthread_join() call with a non-NULL value_ptr argument, the value passed to pthread_exit() ?by ?the ?terminating ?thread shall ?be ?made ?available ?in the location referenced by rval_ptr. When a pthread_join() returns successfully, the target thread has been terminated. The results of multiple simultaneous calls to pthread_join() specifying the same target thread are undefined. If the thread calling pthread_join() is canceled, then the target thread shall not be detached.
pthread_join用于掛起當(dāng)前線程(調(diào)用pthread_join的線程),直到thread指定的線程終止運(yùn)行為止,當(dāng)前線程才繼續(xù)執(zhí)行。thread指定的線程的返回值由rval_ptr返回。一個(gè)線程所使用的資源在對該線程調(diào)用pthread_join之前不會(huì)被重新分配,因此對于每個(gè)切入的線程必須調(diào)用一次pthread_join函數(shù)。線程必須可切入的而不是處于被分離狀態(tài),并且其他線程不能對同一線程再次應(yīng)用pthread_join調(diào)用。通過pthread_create調(diào)用中使用一個(gè)適當(dāng)?shù)腶ttr參數(shù)或者調(diào)用pthread_detach可以讓一個(gè)線程處于被分離狀態(tài)。
- /******************************************************************************************** ?
- **????Name:pthread_join.c ?
- **????Used?to?study?the?multithread?programming?in?Linux?OS ?
- **????A?example?showing?a?thread?to?be?waited?to?end. ?
- **????Author:zeickey ?
- **????Date:2008/6/28???????? ?
- **????Copyright?(c)?2006,All?Rights?Reserved! ?
- *********************************************************************************************/ ??
- ??
- #include?<pthread.h> ??
- #include?<unistd.h> ??
- #include?<stdio.h> ??
- void ?* thread ( void ?*str)??
- {??
- ???? int ?i;??
- ???? for ?(i?=?0;?i?<?10;?++i)??
- ????{??
- ????????sleep(2);??
- ????????printf(? "This?in?the?thread?:?%d/n" ?,?i?);??
- ????}??
- ???? return ?NULL;??
- }??
- ??
- int ?main()??
- {??
- ????pthread_t?pth;??
- ???? int ?i;??
- ???? int ?ret?=?pthread_create(&pth,?NULL,? thread ,?( void ?*)(i));??
- ??????
- ????pthread_join(pth,?NULL);??
- ???? for ?(i?=?0;?i?<?10;?++i)??
- ????{??
- ????????sleep(1);??
- ????????printf(? "This?in?the?main?:?%d/n" ?,?i?);??
- ????}??
- ??????
- ???? return ?0;??
- }??
"pthread_join(pth, NULL);"這一行注釋掉:
[root@localhost src]# gcc pthread_join.c -lpthread
[root@localhost src]# ./a.out
This in the main : 0
This in the thread : 0
This in the main : 1
This in the main : 2
This in the thread : 1
This in the main : 3
This in the main : 4
This in the thread : 2
This in the main : 5
This in the main : 6
This in the thread : 3
This in the main : 7
This in the main : 8
This in the thread : 4
This in the main : 9
子線程還沒有執(zhí)行完畢,main函數(shù)已經(jīng)退出,那么子線程也就退出了。
“pthread_join(pth, NULL);”起作用
[root@localhost src]# gcc pthread_join.c -lpthread
[root@localhost src]# ./a.out
This in the thread : 0
This in the thread : 1
This in the thread : 2
This in the thread : 3
This in the thread : 4
This in the thread : 5
This in the thread : 6
This in the thread : 7
This in the thread : 8
This in the thread : 9
This in the main : 0
This in the main : 1
This in the main : 2
This in the main : 3
This in the main : 4
This in the main : 5
This in the main : 6
This in the main : 7
This in the main : 8
This in the main : 9
[root@localhost src]#
這說明pthread_join函數(shù)的調(diào)用者在等待子線程退出后才繼續(xù)執(zhí)行
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
