POSIX 线程编程(二)线程建立与终止
創(chuàng)建與終止線程
線程的管理常用的API有:
pthread_create(thread,attr,start_routine,arg) pthread_exit(status) pthread_cancel(thread) pthread_attr_init(attr) pthread_attr_destroy(attr)創(chuàng)建線程:
-
一個(gè)main程序包含一個(gè)默認(rèn)的主線程,這個(gè)主線程在程序開(kāi)始運(yùn)行的時(shí)候由系統(tǒng)創(chuàng)建。除此之外的所有其他線程必須由程序員顯式的創(chuàng)建。
-
pthread_create 創(chuàng)建一個(gè)可執(zhí)行的線程。每次調(diào)用創(chuàng)建一個(gè)線程,同時(shí),你可以在任何位置調(diào)用該函數(shù)。
-
pthread_create 參數(shù):
- thread:唯一標(biāo)示一個(gè)新線程的用戶不可見(jiàn)的標(biāo)識(shí)符,由pthread_create產(chǎn)生
- attr:一個(gè)線程的不可見(jiàn)的屬性對(duì)象,可以用來(lái)設(shè)置新建線程的屬性。可以傳進(jìn)一個(gè)線程屬性對(duì)象,類型為pthread_attr_t;或者傳NULL來(lái)使用默認(rèn)值。
- start_routine: 新線程創(chuàng)建好之后由新線程立即執(zhí)行的子程序
- arg:傳給 start_routine的一個(gè)參數(shù)。它必須為void類型的指針,當(dāng)然沒(méi)有參數(shù)或者使用默認(rèn)可以傳NULL。如果想傳進(jìn)多個(gè)參數(shù),可以它們封裝進(jìn)一個(gè)結(jié)構(gòu)體。
-
一個(gè)進(jìn)程可以創(chuàng)建的線程數(shù)量的最大值在不同的系統(tǒng)內(nèi)有不同的實(shí)現(xiàn)。
-
在Linux查詢和設(shè)置你的系統(tǒng)的線程數(shù)量限制方法如下:
-
bash / ksh / shtcsh / csh $ ulimit -a core file size (blocks, -c) 16 data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 255956 max locked memory (kbytes, -l) 64 max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) unlimited cpu time (seconds, -t) unlimited max user processes (-u) 1024 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited$ ulimit -Hu 7168$ ulimit -u 7168$ ulimit -a core file size (blocks, -c) 16 data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 255956 max locked memory (kbytes, -l) 64 max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) unlimited cpu time (seconds, -t) unlimited max user processes (-u) 7168 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited % limit cputime unlimited filesize unlimited datasize unlimited stacksize unlimited coredumpsize 16 kbytes memoryuse unlimited vmemoryuse unlimited descriptors 1024 memorylocked 64 kbytes maxproc 1024% limit maxproc unlimited% limit cputime unlimited filesize unlimited datasize unlimited stacksize unlimited coredumpsize 16 kbytes memoryuse unlimited vmemoryuse unlimited descriptors 1024 memorylocked 64 kbytes maxproc 7168 -
一旦建立,線程之間是并行的,同時(shí)可以在線程內(nèi)創(chuàng)建新的線程。線程之間沒(méi)有繼承或者依賴關(guān)系。
? ? ?
線程屬性
-
默認(rèn)情況下,一個(gè)線程創(chuàng)建之后包含一些默認(rèn)屬性。其中一些可以由傳遞進(jìn)去的線程屬性對(duì)象改變。
-
pthread_attr_init 和 pthread_attr_destroy 用來(lái)初始化和銷毀一個(gè)線程屬性對(duì)象
-
還有一些其他API可以用來(lái)查詢或者設(shè)置線程屬性對(duì)象中的特定的屬性。線程的屬性包括:
- 分離或可結(jié)合狀態(tài)
- 調(diào)度繼承
- 調(diào)度策略
- 調(diào)度參數(shù)
- 調(diào)度競(jìng)爭(zhēng)范圍
- 棧尺寸
- 棧地址
- 棧保護(hù)區(qū)大小
終止線程 pthread_exit():
-
線程在以下幾種情況下會(huì)終止:
- 線程從其start_routine正常返回,其工作全部完成
- 線程調(diào)用了pthread_exit(),無(wú)論其工作是否完成
- 線程被其他線程通過(guò)調(diào)用pthread_cancel()取消
- 線程所在的進(jìn)程調(diào)用了exec() 或者 exit()
- main()函數(shù)結(jié)束
-
pthread_exit()允許程序員指定一個(gè)可選的終止?fàn)顟B(tài)參數(shù)。這個(gè)可選的參數(shù)通常將返回線程“加入”終止線程。
- pthread_exit()不會(huì)關(guān)閉文件,任何在線程內(nèi)打開(kāi)的文件在線程通過(guò)調(diào)用pthread_exit()終止后仍繼續(xù)保持打開(kāi)狀態(tài)。
線程的創(chuàng)建和終止示例代碼
- 在這個(gè)簡(jiǎn)單的例子中將通過(guò)調(diào)用prhtread_ctreate()建立5個(gè)線程,每個(gè)線程輸出“Hello World!”,然后調(diào)用pthread_exit()終止。這里是結(jié)果
- 1 #include <pthread.h>
2 #include <stdio.h>
3 #define NUM_THREADS 5
4
5 void *PrintHello(void *threadid)
6 {
7 long tid;
8 tid = (long)threadid;
9 printf("Hello World! It's me, thread #%ld!\n", tid);
10 pthread_exit(NULL);
11 }
12
13 int main (int argc, char *argv[])
14 {
15 pthread_t threads[NUM_THREADS];
16 int rc;
17 long t;
18 for(t=0; t<NUM_THREADS; t++){
19 printf("In main: creating thread %ld\n", t);
20 rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
21 if (rc){
22 printf("ERROR; return code from pthread_create() is %d\n", rc);
23 exit(-1);
24 }
25 }
26
27 /* Last thing that main() should do */
28 pthread_exit(NULL);
29 }
?
向線程傳遞參數(shù)
-
pthread_create()允許傳遞一個(gè)參數(shù)到線程啟動(dòng)時(shí)調(diào)用的函數(shù)即所謂的start_routine。在需要傳多個(gè)參數(shù)的時(shí)候,可以通過(guò)創(chuàng)建一個(gè)封裝很多參數(shù)的結(jié)構(gòu)體,然后將指向該結(jié)構(gòu)體的指針傳給 pthread_create()就可以了。
-
所有的參數(shù)必須以指針形式傳遞,同時(shí)轉(zhuǎn)為類型為void。
-
線程傳遞參數(shù)的示例代碼:這里是結(jié)果
- 1 /****************************************************************************** 2 * FILE: hello_arg1.c 3 * DESCRIPTION: 4 * A "hello world" Pthreads program which demonstrates one safe way 5 * to pass arguments to threads during thread creation. 6 ******************************************************************************/ 7 #include <pthread.h> 8 #include <stdio.h> 9 #include <stdlib.h> 10 #define NUM_THREADS 8 11 12 char *messages[NUM_THREADS]; 13 14 void *PrintHello(void *threadid) 15 { 16 int *id_ptr, taskid; 17 18 sleep(1); 19 id_ptr = (int *) threadid; 20 taskid = *id_ptr; 21 printf("Thread %d: %s\n", taskid, messages[taskid]); 22 pthread_exit(NULL); 23 } 24 25 int main(int argc, char *argv[]) 26 { 27 pthread_t threads[NUM_THREADS]; 28 int *taskids[NUM_THREADS]; 29 int rc, t; 30 31 messages[0] = "English: Hello World!"; 32 messages[1] = "French: Bonjour, le monde!"; 33 messages[2] = "Spanish: Hola al mundo"; 34 messages[3] = "Klingon: Nuq neH!"; 35 messages[4] = "German: Guten Tag, Welt!"; 36 messages[5] = "Russian: Zdravstvytye, mir!"; 37 messages[6] = "Japan: Sekai e konnichiwa!"; 38 messages[7] = "Latin: Orbis, te saluto!"; 39 40 for(t=0;t<NUM_THREADS;t++) { 41 taskids[t] = (int *) malloc(sizeof(int)); 42 *taskids[t] = t; 43 printf("Creating thread %d\n", t); 44 rc = pthread_create(&threads[t], NULL, PrintHello, (void *) taskids[t]); 45 if (rc) { 46 printf("ERROR; return code from pthread_create() is %d\n", rc); 47 exit(-1); 48 } 49 } 50 51 pthread_exit(NULL); 52 }
? ? ? ? ?傳遞多個(gè)參數(shù)的例子,請(qǐng)看這里
Joining and Detaching 線程
pthread_join(threadid,status) pthread_detach(threadid) pthread_attr_setdetachstate(attr,detachstate) pthread_atr_getdetachstate(attr,detachstate)-
Joining:
-
"Joining"是線程間同步的一種方式。
-
pthread_join()會(huì)阻塞調(diào)用的線程直至制定的threadid線程終止
-
如果在指定的目標(biāo)線程中調(diào)用pthread_exit(),程序員可以獲得目標(biāo)線程的終止返回狀態(tài)。
-
線程一個(gè)創(chuàng)建,其中的一個(gè)屬性就被制定為joinable或者detached。而且只有joinable的線程才可以使用這種同步方式。
-
顯式的創(chuàng)建一個(gè)線程為joinable或者detached,可以在pthread_create()中使用屬性參數(shù),步驟如下: 1) 聲明一個(gè)線程屬性變量,類型為pthread_attr_t 2) 使用pthread_attr_init()初始化屬性變量 3) 使用pthread_attr_setdetachstate()設(shè)置屬性分離狀態(tài) 4) 程序結(jié)束時(shí),使用pthread_attr_destroy()釋放屬性對(duì)象使用的資源
-
還有兩種同步方法,互斥鎖和條件變量,將在以后的blog中討論
-
-
Detaching
-
pthread_detach()可以顯式的detach一個(gè)線程即便它創(chuàng)建的時(shí)候是joinable。
-
沒(méi)有相反的API
-
-
Pthread Joining示例代碼如下:這里是結(jié)果
1 /***************************************************************************** 2 * FILE: join.c 3 * DESCRIPTION: 4 * This example demonstrates how to "wait" for thread completions by using 5 * the Pthread join routine. Threads are explicitly created in a joinable 6 * state for portability reasons. Use of the pthread_exit status argument is 7 * also shown. Compare to detached.c 8 ******************************************************************************/ 9 #include <pthread.h> 10 #include <stdio.h> 11 #include <stdlib.h> 12 #define NUM_THREADS 4 13 14 void *BusyWork(void *t) 15 { 16 int i; 17 long tid; 18 double result=0.0; 19 tid = (long)t; 20 printf("Thread %ld starting...\n",tid); 21 for (i=0; i<1000000; i++) 22 { 23 result = result + sin(i) * tan(i); 24 } 25 printf("Thread %ld done. Result = %e\n",tid, result); 26 pthread_exit((void*) t); 27 } 28 29 int main (int argc, char *argv[]) 30 { 31 pthread_t thread[NUM_THREADS]; 32 pthread_attr_t attr; 33 int rc; 34 long t; 35 void *status; 36 37 /* Initialize and set thread detached attribute */ 38 pthread_attr_init(&attr); 39 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 40 41 for(t=0; t<NUM_THREADS; t++) { 42 printf("Main: creating thread %ld\n", t); 43 rc = pthread_create(&thread[t], &attr, BusyWork, (void *)t); 44 if (rc) { 45 printf("ERROR; return code from pthread_create() is %d\n", rc); 46 exit(-1); 47 } 48 } 49 50 /* Free attribute and wait for the other threads */ 51 pthread_attr_destroy(&attr); 52 for(t=0; t<NUM_THREADS; t++) { 53 rc = pthread_join(thread[t], &status); 54 if (rc) { 55 printf("ERROR; return code from pthread_join() is %d\n", rc); 56 exit(-1); 57 } 58 printf("Main: completed join with thread %ld having a status of %ld\n",t,(long)status); 59 } 60 61 printf("Main: program completed. Exiting.\n"); 62 pthread_exit(NULL); 63 }?
轉(zhuǎn)載于:https://www.cnblogs.com/nicganon/p/3735434.html
總結(jié)
以上是生活随笔為你收集整理的POSIX 线程编程(二)线程建立与终止的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: eclipse安装Hadoop1.1.2
- 下一篇: fscanf和feof的组合使用