Linux系統下的多線程遵循POSIX線程接口,稱為pthread。編寫Linux下的多線程程序,需要使用頭文件pthread.h,連接時需 要使用庫libpthread.a。順便說壹下,Linux下pthread的實現是通過系統調用clone()來實現的。clone()是Linux所 特有的系統調用,它的使用方式類似fork,關於clone()的詳細情況,有興趣的讀者可以去查看有關文檔說明。下面我們展示壹個最簡單的多線程程序 example1.c。
/* example.c*/
#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);
}
我們編譯此程序:
gcc example1.c -lpthread -o example1
運行example1,我們得到如下結果:
This is the main process.
This is a pthread.
This is the main process.
This is the main process.
This is a pthread.
This is a pthread.
再次運行,我們可能得到如下結果:
This is a pthread.
This is the main process.
This is a pthread.
This is the main process.
This is a pthread.
This is the main process.
前後兩次結果不壹樣,這是兩個線程爭奪CPU資源的結果。上面的示例中,我們使用到了兩個函數, pthread_create和pthread_join,並聲明了壹個pthread_t型的變量。
pthread_t在頭文件/usr/include/bits/pthreadtypes.h中定義:
typedef unsigned long int pthread_t;
它是壹個線程的標識符。函數pthread_create用來創建壹個線程,它的原型為:
extern int pthread_create __P ((pthread_t *__thread, __const pthread_attr_t *__attr,
void *(*__start_routine) (void *), void *__arg));
第壹個參數為指向線程標識符的指針,第二個參數用來設置線程屬性,第三個參數是線程運行函數的起始地址,最後壹個參數是運行函數的參數。這裏,我們的 函數thread不需要參數,所以最後壹個參數設為空指針。第二個參數我們也設為空指針,這樣將生成默認屬性的線程。對線程屬性的設定和修改我們將在下壹 節闡述。當創建線程成功時,函數返回0,若不為0則說明創建線程失敗,常見的錯誤返回代碼為EAGAIN和EINVAL。前者表示系統限制創建新的線程, 例如線程數目過多了;後者表示第二個參數代表的線程屬性值非法。創建線程成功後,新創建的線程則運行參數三和參數四確定的函數,原來的線程則繼續運行下壹 行代碼。
函數pthread_join用來等待壹個線程的結束。函數原型為:
extern int pthread_join __P ((pthread_t __th, void **__thread_return));
第壹個參數為被等待的線程標識符,第二個參數為壹個用戶定義的指針,它可以用來存儲被等待線程的返回值。這個函數是壹個線程阻塞的函數,調用它的函數 將壹直等待到被等待的線程結束為止,當函數返回時,被等待線程的資源被收回。壹個線程的結束有兩種途徑,壹種是象我們上面的例子壹樣,函數結束了,調用它 的線程也就結束了;另壹種方式是通過函數pthread_exit來實現。它的函數原型為:
extern void pthread_exit __P ((void *__retval)) __attribute__ ((__noreturn__));
唯壹的參數是函數的返回代碼,只要pthread_join中的第二個參數thread_return不是NULL,這個值將被傳遞給 thread_return。最後要說明的是,壹個線程不能被多個線程等待,否則第壹個接收到信號的線程成功返回,其余調用pthread_join的線 程則返回錯誤代碼ESRCH。
在這壹節裏,我們編寫了壹個最簡單的線程,並掌握了最常用的三個函數pthread_create,pthread_join和pthread_exit。下面,我們來了解線程的壹些常用屬性以及如何設置這些屬性。