Table of Contents
基本線程的動作
繼續之前C語言線程的文章:文章1 文章2 來了解基本的線程操作。
設置線程屬性
設置脫離狀態
下面代碼中關鍵的地方在於:
- 通過 res = pthread_attr_init(&thread_attr);
初始化一個線程屬性
- 通過 res = pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
將屬性設置爲脫離狀態(PTHREAD_CREATE_DETACHED
),即不能通過調用 pthread_join
來獲得另一個線程的退出狀態
- 另外還有一個常用的默認狀態是 PTHREAD_CREATE_JOINABLE
,可以允許兩個線程重新合併。
- 屬性用完後對其進行清理回收 (void)pthread_attr_destroy(&thread_attr);
- 通過共享的變量 thread_finished
來檢測子線程是否已經結束
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
void *thread_function(void *arg);
char message[] = "Hello World";
int thread_finished = 0;
int main() {
int res;
pthread_t a_thread;
pthread_attr_t thread_attr;
res = pthread_attr_init(&thread_attr);
if (res != 0) {
perror("Attribute creation failed");
exit(EXIT_FAILURE);
}
res = pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
if (res != 0) {
perror("Setting detached attribute failed");
exit(EXIT_FAILURE);
}
res = pthread_create(&a_thread, &thread_attr, thread_function, (void *)message);
if (res != 0) {
perror("Thread creation failed");
exit(EXIT_FAILURE);
}
(void)pthread_attr_destroy(&thread_attr);
while(!thread_finished) {
printf("Waiting for thread to say it's finished...\n");
sleep(1);
}
printf("Other thread finished, bye!\n");
exit(EXIT_SUCCESS);
}
void *thread_function(void *arg){
printf("thread_function is running. Argument was %s\n", (char *)arg);
sleep(4);
printf("Second thread setting finished flag, and exiting now\n");
thread_finished = 1;
pthread_exit(NULL);
}
設置調度屬性
線程庫提供以下調度策略:
| SCHED_FIFO | 先進先出 (FIFO) 調度。每個線程都有一個固定的優先級;當多個線程具有相同的優先級時,它們按照先進先出 (FIFO) 的順序運行直到完成 |
| SCHED_RR | 循環 (RR) 調度。每個線程都有固定的優先級;當多個線程具有相同的優先級時,它們按照先進先出 (FIFO) 的順序在一個 固定的時間片內運行。 |
| SCHED_OTHER | 缺省的 AIX® 調度。每個線程都有一個由調度程序根據線程的活動動態修改的初始優先級;線程的執行是按時間分割的。在其他系統上,這個調度策略可能會不同。 |
設置調度屬性和設置很相似:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
void *thread_function(void *arg);
char message[] = "Hello World";
int thread_finished = 0;
int main() {
int res;
pthread_t a_thread;
pthread_attr_t thread_attr;
int max_priority;
int min_priority;
struct sched_param scheduling_value;
res = pthread_attr_init(&thread_attr);
if (res != 0) {
perror("Attribute creation failed");
exit(EXIT_FAILURE);
}
res = pthread_attr_setschedpolicy(&thread_attr, SCHED_OTHER);
if (res != 0) {
perror("Setting schedpolicy failed");
exit(EXIT_FAILURE);
}
res = pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
if (res != 0) {
perror("Setting detached attribute failed");
exit(EXIT_FAILURE);
}
res = pthread_create(&a_thread, &thread_attr, thread_function, (void *)message);
if (res != 0) {
perror("Thread creation failed");
exit(EXIT_FAILURE);
}
max_priority = sched_get_priority_max(SCHED_OTHER);
min_priority = sched_get_priority_min(SCHED_OTHER);
scheduling_value.sched_priority = min_priority;
res = pthread_attr_setschedparam(&thread_attr, &scheduling_value);
if (res != 0) {
perror("Setting schedpolicy failed");
exit(EXIT_FAILURE);
}
(void)pthread_attr_destroy(&thread_attr);
while(!thread_finished) {
printf("Waiting for thread to say it's finished...\n");
sleep(1);
}
printf("Other thread finished, bye!\n");
exit(EXIT_SUCCESS);
}
void *thread_function(void *arg) {
printf("thread_function is running. Argument was %s\n", (char *)arg);
sleep(4);
printf("Second thread setting finished flag, and exiting now\n");
thread_finished = 1;
pthread_exit(NULL);
}
取消線程
- 通過
int pthread_cancel(pthread_t thread);
來請求一個線程終止 - 通過
int pthread_setcancelstate(int state, int *oldstate)
來設置接受的進程是允許取消請求還是忽略它 通過
int pthread_setcanceltype(int type, int *oldtype
) 來設置取消類型,PTHREAD_CANCEL_ASYCHRONOUS
代表接收到取消請求後立即行動,THREAD_CANCEL_DEFERRED
表示在接收到請求後,等待函數執行下述動作之一後才取消線程:pthread_join, pthread_cond_wait, pthread_cond_timeout, pthread_test_cancel, sem_wait, sigwait
等include
主線程創建多個線程示例
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#define NUM_THREADS 6
void *thread_function(void *arg);
int main() {
int res;
pthread_t a_thread[NUM_THREADS];
void *thread_result;
int lots_of_threads;
for(lots_of_threads = 0; lots_of_threads < NUM_THREADS; lots_of_threads++) {
res = pthread_create(&(a_thread[lots_of_threads]), NULL, thread_function, (void *)&lots_of_threads);
if (res != 0) {
perror("Thread creation failed");
exit(EXIT_FAILURE);
}
sleep(1);
}
printf("Waiting for threads to finish...\n");
for(lots_of_threads = NUM_THREADS - 1; lots_of_threads >= 0; lots_of_threads--) {
res = pthread_join(a_thread[lots_of_threads], &thread_result);
if (res == 0) {
printf("Picked up a thread\n");
}
else {
perror("pthread_join failed");
}
}
printf("All done\n");
exit(EXIT_SUCCESS);
}
void *thread_function(void *arg) {
int my_number = *(int *)arg;
int rand_num;
printf("thread_function is running. Argument was %d\n", my_number);
rand_num=1+(int)(9.0*rand()/(RAND_MAX+1.0));
sleep(rand_num);
printf("Bye from %d\n", my_number);
pthread_exit(NULL);
}
運行結果如下:
thread_function is running. Argument was 0
Bye from 0
thread_function is running. Argument was 1
thread_function is running. Argument was 2
Bye from 1
thread_function is running. Argument was 3
thread_function is running. Argument was 4
thread_function is running. Argument was 5
Waiting for threads to finish...
Bye from 5
Picked up a thread
Bye from 3
Bye from 2
Bye from 4
Picked up a thread
Picked up a thread
Picked up a thread
Picked up a thread
Picked up a thread
All done
瞭解更多
參考資料
- 《Linux 程序設計》
- http://www.ibm.com/support/knowledgecenter/zh/ssw_aix_61/com.ibm.aix.genprogc/threads_sched.htm
PS
不得不承認,我失敗了。曾計劃每天分享一篇python相關知識點但沒有做到。失敗的原因想找可以找很多比如最近在做一個小的項目、這幾天出去聚會沒有時間、工作出現問題加班到比較晚等等,然而總結起來不外乎在心裏它的重要程度是怎麼樣的。我反思了下幾乎做到一天一篇的這一個月過程做出改變,不再要求一天一篇,而是當我有好的素材要分享時才分享,這樣與我與大家都是一件好事,我可以動態調度自己的精力和注意力,比如最近實現了一半的一個odoo項目依賴關係分析器可以儘快把它做完,對於讀者來說也可以減少干擾看到更好的分享而不是像我之前有幾篇那樣划水的。但每週應該會有3-4篇Python的知識可以分享。另外我目前的工作是基於Odoo的,我計劃嘗試做一些基礎的教程來分享這個我熟悉的框架,如果有進展一定會告知感興趣的讀者。感謝讀者。
最後向漩渦鳴人致敬,朝他的“說到做到,這就是我的忍道”努力。