第十二章 POSIX 執行緒(一)

2021-09-30 10:08:00 字數 3611 閱讀 5563

在乙個程式中的多個執行線路就叫做執行緒(thread)。更準確的定義是:執行緒是乙個程序內部的乙個控制序列。

執行緒有一套完整的與其相關的函式庫呼叫,它們中的絕大多數函式名都是以 pthread_ 開頭,為了使用這些函式庫呼叫,我們必須定義巨集 _peentrant,在程式中包含頭文

件 pthread.h ,並且在編譯程式的時需要用選項 -lpthread 來鏈結執行緒庫。

pthread_create

它的作用是建立乙個新執行緒,類似於建立新程序的 fork 函式。它的定義如下:

#include

int pthread_create ( pthread_t *thread, pthread_attr_t *attr, void

* ( *start_routine ) ( void * ), void *arg );

第乙個引數是指向 pthread_t 型別資料的指標。執行緒被建立時,這個指標指向的變數中將被寫入乙個識別符號,我們用該識別符號來引用新執行緒。下乙個引數用於設定執行緒的屬性。我們一般不需要特殊的屬性,所以只需設定該引數為 null。最後兩個引數分別告訴執行緒將要啟動執行的函式和傳遞給該函式的引數。

void * ( *start_routine ) ( void * )

上面一行告訴我們必須要傳遞乙個函式位址,該函式以乙個指向 void 的指標為引數,返回的也是乙個指向 void 的指標。因此,可以傳遞乙個任一型別的引數並返回乙個任一型別的指標。用 fork 呼叫後,父程序將在同一位置繼續執行下去,只是 fork 呼叫的返回值是不同的;但對新執行緒來說,我們必須明確地提供給它乙個函式指標,新執行緒將在這個新位置開始執行。

該函式呼叫成功時返回值是 0,如果失敗則返回錯誤**。

執行緒通過呼叫 pthread_exit 函式終止執行,就如同程序在結束時呼叫 exit 函式一樣。這個函式的作用是,終止呼叫它的執行緒並返回乙個指向某個物件的指標。注意,絕不能用它來返回乙個指向區域性變數的指標,因為執行緒呼叫該函式後,這個區域性變數就不再存在了,這將引起嚴重的程式漏洞。

pthread_exit 函式定義如下:

#include

void pthread_exit ( void *retval );

#include

int pthread_join ( pthread_t th, void **thread_return );

第乙個引數指定了將要等待的執行緒,執行緒通過 pthread_create 返回的識別符號來指定。第二個引數是乙個指標,它指向另乙個指標,而後者指向執行緒的返回值。與 pthread_create 類似,這個函式在成功時返回0,失敗時返回錯誤**。

#include #include #include #include #include void *thread_function(void *arg);

char message = "hello world";

int main()

printf("waiting for thread to finish...\n");

res = pthread_join(a_thread, &thread_result);

if (res != 0)

printf("thread joined, it returned %s\n", (char *)thread_result);

printf("message is now %s\n", message);

exit(exit_success);

}void *thread_function(void *arg)

$ ./thread1

waiting for thread to finish...

thread_function is running. argument was hello world

thread joined, it returned thank you for the cpu time

message is now bye!

實驗解析

首先,我們定義了在建立執行緒時需要由它呼叫的乙個函式原型。如下所示:

void *thread_function ( void *arg );

根據 pthread_create 的要求,它只有乙個指向 void 的指標作為引數,返回的也是指向 void 的指標。稍後,將介紹這個函式的實現。

在 main 函式中,我們首先定義了幾個變數,然後呼叫 pthread_create 開始執行新執行緒。如下所示:

pthread_t a_thread;

void *thread_result;

res = pthread_create(&a_thread, null, thread_function, (void *)message);

我們向 pthread_create 函式傳遞了乙個 pthread_t 型別物件的位址,今後可以用它來引用這個新執行緒。我們不想改變預設的執行緒屬性,所以設第二個引數為 null。最後兩個引數分別為將要呼叫的函式和乙個傳遞給該函式的引數。

如果這個呼叫成功了,就會有兩個執行緒在執行。原先的執行緒(main)繼續執行 pthread_create 後面的**,而新執行緒開始執行 thread_function 函式。

原先的執行緒在查明新執行緒已經啟動後,將呼叫 pthread_join 函式。如下所示:

res = pthread_join ( a_thread, &thread_result );

我們給乾旱數傳遞兩個引數,乙個是正在等待其結束的執行緒的識別符號,另乙個是指向執行緒返回值的指標。這個函式將等到它所指定的執行緒終止後才返回。然後主線程將列印新執行緒的返回值和全域性變數 message 的值,然後退出。

新執行緒在 thread_function 函式中開始執行,它先列印出自己的引數,休眠一會兒,然後更新全域性變數,最後退出並向主線程返回乙個字串。新執行緒修改了陣列 message。而原先的執行緒也可以訪問該陣列。如果我們呼叫的是 fork 而不是 pthread_create ,就不會有這樣的效果。

同時執行(輪詢技術)

#include #include #include #include void *thread_function(void *arg);

int run_now = 1;

char message = "hello world";

int main()

while(print_count1++ < 20)

else

}printf("\nwaiting for thread to finish...\n");

res = pthread_join(a_thread, &thread_result);

if (res != 0)

printf("thread joined\n");

exit(exit_success);

}void *thread_function(void *arg)

else

}sleep(3);

}

$ cc -d_reentrant thread3.c -o thread2 -lpthread

$ ./thread2

12121212121212121212

waiting for thread to finish...

thread joined

第十二章 POSIX 執行緒(三)

用互斥量進行同步 另一種用在多執行緒程式中的同步訪問方法是使用互斥量。它允許程式設計師鎖住某個物件,使得每次只有乙個執行緒訪問它。為了控制對關鍵 的訪問,必須在進入這段 之前鎖住乙個互斥量,然後在完成操作之後解鎖它。include int pthread mutex init pthread mut...

第十二章 執行緒控制

1.執行緒屬性 int pthread attr init pthread attr t attr int pthread attr destroy pthread attr t attr int pthread attr getdetachstate const pthread attr t re...

第十二章 檔案

文字檔案 文字檔案是一種由若干字元構成的檔案,可以用文字編輯器進行閱讀或編輯。以txt py html等為字尾的檔案都是文字檔案。2.二進位制檔案 二進位制檔案一般是指不能用文字編輯器閱讀或編輯的檔案。以 mp4 png等為字尾的檔案都是二進位制檔案,如果想要開啟或修改這些檔案,必須通過特定軟體進行...