Linux 系統(tǒng)下的多線(xiàn)程遵循POSIX線(xiàn)程接口,稱(chēng)為pthread。編寫(xiě)Linux下的多線(xiàn)程程序,需要使用頭文件pthread.h,連接時(shí)需要使用庫(kù) libpthread.a。
1. 線(xiàn)程的創(chuàng)建和使用
線(xiàn)程的創(chuàng)建是用下面的幾個(gè)函數(shù)來(lái)實(shí)現(xiàn)的.
int
?pthread_create(pthread_t?
*
thread,pthread_attr_t?
*
attr,?
void
?
*
(
*
start_routine)(
void
?
*
),
void
?
*
arg);
void
?pthread_exit(
void
?
*
retval);
int
?pthread_join(pthread?
*
thread,
void
?
**
thread_return);
pthread_create創(chuàng)建一個(gè)線(xiàn)程,thread是用來(lái)表明創(chuàng)建線(xiàn)程的ID,attr指出線(xiàn)程創(chuàng)建時(shí)候的屬性,我們用NULL來(lái)表明使用缺省屬性.start_routine函數(shù)指針是線(xiàn)程創(chuàng)建成功后開(kāi)始執(zhí)行的函數(shù),arg是這個(gè)函數(shù)的唯一一個(gè)參數(shù).表明傳遞給start_routine 的參數(shù).
pthread_exit函數(shù)和exit函數(shù)類(lèi)似用來(lái)退出線(xiàn)程.這個(gè)函數(shù)結(jié)束線(xiàn)程,釋放函數(shù)的資源,并在最后阻塞,直到其他線(xiàn)程使用
pthread_join函數(shù)等待它.然后將*retval的值傳遞給**thread_return.由于這個(gè)函數(shù)釋放所以的函數(shù)資源,所以 retval不能夠指向函數(shù)的局部變量.
pthread_join和wait調(diào)用一樣用來(lái)等待指定的線(xiàn)程.
下面展示一個(gè)最簡(jiǎn)單的多線(xiàn)程程序。
#include?
<
stdio.h
>
#include?
<
pthread.h
>
void
?thread(
void
)
{
?
int
?i;
?
for
(i
=
0
;i
<
3
;i
++
)
?printf(
"
This?is?a?pthread.\n
"
);
}
int
?main(
void
)
{
?pthread_t?id;
?
int
?i,ret;
?ret
=
pthread_create(
&
id,NULL,(
void
?
*
)?thread,NULL);
?
if
(ret
!=
0
)
?{
??printf?(
"
Create?pthread?error!\n
"
);
??exit?(
1
);
?}
?
for
(i
=
0
;i
<
3
;i
++
)
??printf(
"
This?is?the?main?process.\n
"
);
?pthread_join(id,NULL);
?
return
?(
0
);
}
2. 修改線(xiàn)程的屬性
上面用pthread_create函數(shù)創(chuàng)建了一個(gè)線(xiàn)程,在這個(gè)線(xiàn)程中,我們使用了默認(rèn)參數(shù),即將該函數(shù)的第二個(gè)參數(shù)設(shè)為NULL。屬性結(jié)構(gòu)為pthread_attr_t,它同樣在頭文件/usr/include/pthread.h中定義。屬性值不能直接設(shè)置,須使用相關(guān)函數(shù)進(jìn)行操作,初始化的函數(shù)為pthread_attr_init,這個(gè)函數(shù)必須在pthread_create函數(shù)之前調(diào)用。屬性對(duì)象主要包括是否綁定、是否分離、堆棧地址、堆棧大小、優(yōu)先級(jí)。默認(rèn)的屬性為非綁定、非分離、缺省1M的堆棧、與父進(jìn)程同樣級(jí)別的優(yōu)先級(jí)。
關(guān)于線(xiàn)程的綁定,牽涉到另外一個(gè)概念:輕進(jìn)程(LWP:Light Weight Process)。輕進(jìn)程可以理解為內(nèi)核線(xiàn)程,它位于用戶(hù)層和系統(tǒng)層之間。系統(tǒng)對(duì)線(xiàn)程資源的分配、對(duì)線(xiàn)程的控制是通過(guò)輕進(jìn)程來(lái)實(shí)現(xiàn)的,一個(gè)輕進(jìn)程可以控制一個(gè)或多個(gè)線(xiàn)程。默認(rèn)狀況下,啟動(dòng)多少輕進(jìn)程、哪些輕進(jìn)程來(lái)控制哪些線(xiàn)程是由系統(tǒng)來(lái)控制的,這種狀況即稱(chēng)為非綁定的。綁定狀況下,則顧名思義,即某個(gè)線(xiàn)程固定的"綁"在一個(gè)輕進(jìn)程之上。被綁定的線(xiàn)程具有較高的響應(yīng)速度,這是因?yàn)镃PU時(shí)間片的調(diào)度是面向輕進(jìn)程的,綁定的線(xiàn)程可以保證在需要的時(shí)候它總有一個(gè)輕進(jìn)程可用。通過(guò)設(shè)置被綁定的輕進(jìn)程的優(yōu)先級(jí)和調(diào)度級(jí)可以使得綁定的線(xiàn)程滿(mǎn)足諸如實(shí)時(shí)反應(yīng)之類(lèi)的要求。
設(shè)置線(xiàn)程綁定狀態(tài)的函數(shù)為pthread_attr_setscope,它有兩個(gè)參數(shù),第一個(gè)是指向?qū)傩越Y(jié)構(gòu)的指針,第二個(gè)是綁定類(lèi)型,它有兩個(gè)取值:PTHREAD_SCOPE_SYSTEM(綁定的)和PTHREAD_SCOPE_PROCESS(非綁定的)。下面的代碼即創(chuàng)建了一個(gè)綁定的線(xiàn)程。
#include?
<
pthread.h
>
pthread_attr_t?attr;
pthread_t?tid;
/*
初始化屬性值,均設(shè)為默認(rèn)值
*/
pthread_attr_init(
&
attr);
pthread_attr_setscope(
&
attr,?PTHREAD_SCOPE_SYSTEM);
pthread_create(
&
tid,?
&
attr,?(
void
?
*
)?my_function,?NULL);
線(xiàn)程的分離狀態(tài)決定一個(gè)線(xiàn)程以什么樣的方式來(lái)終止自己。在上面的例子中,我們采用了線(xiàn)程的默認(rèn)屬性,即為非分離狀態(tài),這種情況下,原有的線(xiàn)程等待創(chuàng)建的線(xiàn)程結(jié)束。只有當(dāng)pthread_join()函數(shù)返回時(shí),創(chuàng)建的線(xiàn)程才算終止,才能釋放自己占用的系統(tǒng)資源。而分離線(xiàn)程不是這樣子的,它沒(méi)有被其他的線(xiàn)程所等待,自己運(yùn)行結(jié)束了,線(xiàn)程也就終止了,馬上釋放系統(tǒng)資源。程序員應(yīng)該根據(jù)自己的需要,選擇適當(dāng)?shù)姆蛛x狀態(tài)。設(shè)置線(xiàn)程分離狀態(tài)的函數(shù)為 pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)。第二個(gè)參數(shù)可選為PTHREAD_CREATE_DETACHED(分離線(xiàn)程)和 PTHREAD_CREATE_JOINABLE(非分離線(xiàn)程)。這里要注意的一點(diǎn)是,如果設(shè)置一個(gè)線(xiàn)程為分離線(xiàn)程,而這個(gè)線(xiàn)程運(yùn)行又非常快,它很可能在 pthread_create函數(shù)返回之前就終止了,它終止以后就可能將線(xiàn)程號(hào)和系統(tǒng)資源移交給其他的線(xiàn)程使用,這樣調(diào)用pthread_create的線(xiàn)程就得到了錯(cuò)誤的線(xiàn)程號(hào)。要避免這種情況可以采取一定的同步措施,最簡(jiǎn)單的方法之一是可以在被創(chuàng)建的線(xiàn)程里調(diào)用 pthread_cond_timewait函數(shù),讓這個(gè)線(xiàn)程等待一會(huì)兒,留出足夠的時(shí)間讓函數(shù)pthread_create返回。設(shè)置一段等待時(shí)間,是在多線(xiàn)程編程里常用的方法。但是注意不要使用諸如wait()之類(lèi)的函數(shù),它們是使整個(gè)進(jìn)程睡眠,并不能解決線(xiàn)程同步的問(wèn)題。
另外一個(gè)可能常用的屬性是線(xiàn)程的優(yōu)先級(jí),它存放在結(jié)構(gòu)sched_param中。用函數(shù)pthread_attr_getschedparam和函數(shù) pthread_attr_setschedparam進(jìn)行存放,一般說(shuō)來(lái),我們總是先取優(yōu)先級(jí),對(duì)取得的值修改后再存放回去。下面即是一段簡(jiǎn)單的例子。
#include?
<
pthread.h
>
#include?
<
sched.h
>
pthread_attr_t?attr;
pthread_t?tid;
sched_param?param;
int
?newprio
=
20
;
pthread_attr_init(
&
attr);
pthread_attr_getschedparam(
&
attr,?
&
param);
param.sched_priority
=
newprio;
pthread_attr_setschedparam(
&
attr,?
&
param);
pthread_create(
&
tid,?
&
attr,?(
void
?
*
)myfunction,?myarg);
[參考]
http://fanqiang.chinaunix.net/a4/b2/20010508/113838.html
http://fanqiang.chinaunix.net/a4/b8/20010811/0905001105.html