POSIX线程
POSIX線程
標簽(空格分隔): Linux程序設計
什么是線程
線程是一個進程內部的一個控制序列。
當在進程中創建一個新線程時,新的執行線程將擁有自己的棧(因此也有自己的局部變量),但與它的創建者共享全局變量、文件描述符、信號處理函數和當前目錄狀態。
線程的優點:
線程創建相關函數
#include<pthread.h>//創建線程 int pthread_create(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *arg); //thread: 指向pthread_t類型的指針,用來引用該新線程; //attr: 用于設置線程的屬性,一般為NULL; //第3,4個參數為線程將要啟動執行的函數,以及傳遞給該函數的參數 //返回:調用成功返回0,失敗則返回錯誤代碼//線程等待函數 int pthread_join(pthread_t th, void **thread_return); //th: 指定將要等待的線程 //thread_return: 指向線程返回值的指針(的指針)。 //返回:成功返回0,失敗則返回錯誤代碼//線程終止函數 void pthread_exit(void *retval); //retval: 指向線程返回值的指針(pthread_join可以獲取該指針)示例:
#include<stdio.h> #include<unistd.h> #include<stdlib.h> #include<string.h> #include<pthread.h>void *thread_function(void *arg); char msg[] = "Hello World";int main() {int res;pthread_t a_thread;void *thread_result;res = pthread_create(&a_thread, NULL, thread_function, (void *)msg);if(res != 0){perror("Thread creation failed.");exit(EXIT_FAILURE);}printf("Waiting for thread to finish...\n");res = pthread_join(a_thread, &thread_result);if(res != 0){perror("Thread join failed.");exit(EXIT_FAILURE);}printf("Thread joined, it returned %s\n", (char *)thread_result);printf("Message is now %s\n", msg);exit(EXIT_SUCCESS); }void *thread_function(void *arg) {printf("Thread function is runing. Argument was %s\n",(char *)arg);sleep(3);strcpy(msg,"Bye!");pthread_exit("Thank you for the CPU time."); }線程同步
互斥量mutex
參考:https://docs.oracle.com/cd/E19253-01/819-7051/sync-12/index.html
#include<pthread.h>int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr); //mutex: 事先聲明過的pthread_mutex_t對象的指針 //mutexattr: 設置互斥量的屬性,默認為fast。該參數一般置為NULL //返回: 成功返回0,失敗則返回錯誤代碼//加鎖 int pthread_mutex_lock(pthread_mutex_t *mutex);//解鎖 int pthread_mutex_unlock(pthread_mutex_t *mutex);//銷毀 int pthread_mutex_destroy(pthread_mutex_t *mutex);示例:
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <pthread.h>void *thread_function(void *arg); pthread_mutex_t work_mutex; /* protects both work_area and time_to_exit */#define WORK_SIZE 1024 char work_area[WORK_SIZE]; int time_to_exit = 0;int main() {int res;pthread_t a_thread;void *thread_result;res = pthread_mutex_init(&work_mutex, NULL);if (res != 0) {perror("Mutex initialization failed");exit(EXIT_FAILURE);}res = pthread_create(&a_thread, NULL, thread_function, NULL);if (res != 0) {perror("Thread creation failed");exit(EXIT_FAILURE);}pthread_mutex_lock(&work_mutex);printf("Input some text. Enter 'end' to finish\n");while(!time_to_exit) {fgets(work_area, WORK_SIZE, stdin);pthread_mutex_unlock(&work_mutex);while(1) {pthread_mutex_lock(&work_mutex);if (work_area[0] != '\0') {pthread_mutex_unlock(&work_mutex);sleep(1);}else {break;}}}pthread_mutex_unlock(&work_mutex);printf("\nWaiting for thread to finish...\n");res = pthread_join(a_thread, &thread_result);if (res != 0) {perror("Thread join failed");exit(EXIT_FAILURE);}printf("Thread joined\n");pthread_mutex_destroy(&work_mutex);exit(EXIT_SUCCESS); }void *thread_function(void *arg) {sleep(1);pthread_mutex_lock(&work_mutex);while(strncmp("end", work_area, 3) != 0) {printf("You input %d characters\n", strlen(work_area) -1);work_area[0] = '\0';pthread_mutex_unlock(&work_mutex);sleep(1);pthread_mutex_lock(&work_mutex);while (work_area[0] == '\0' ) {pthread_mutex_unlock(&work_mutex);sleep(1);pthread_mutex_lock(&work_mutex);}}time_to_exit = 1;work_area[0] = '\0';pthread_mutex_unlock(&work_mutex);pthread_exit(0); }條件變量
參考:
IBM Knowledge Center: 使用條件變量
知乎:條件變量之稀里糊涂的鎖
有了互斥鎖,為什么還要條件變量?
linux多線程使用pthread_cond條件變量
條件變量(cond)是在多線程程序中用來實現"等待->喚醒"邏輯常用的方法。條件變量利用線程間共享的全局變量進行同步的一種機制。
條件變量必須始終與互斥對象一起使用。主要為了防止競爭死鎖(防止pthread_cond_signal在pthread_cond_wait之前調用,導致線程永久等待)。
保護條件的互斥對象必須在等待條件前被鎖定。線程可等待通過調用 pthread_cond_wait 或者 pthread_cond_timedwait 子例程發信號的條件。子例程以不可分割的方式解鎖互斥對象并阻塞調用線程,直到條件收到信號。當調用返回時,互斥對象再次被鎖定。
pthread_cond_wait 子例程無限期阻塞線程。如果條件永不收到信號,那么線程將永不喚醒。因為 pthread_cond_wait 子例程提供取消點,所以如果啟用可取消,那么退出此死鎖的唯一方法是取消被阻塞的線程。
pthread_cond_wait函數的返回并不意味著條件的值一定發生了變化,必須重新檢查條件的值。
pthread_cond_signal 子例程至少喚醒一個當前在指定條件上被阻塞的線程。根據調度策略選擇被喚醒的線程。
pthread_cond_broadcast 子例程喚醒當前被阻塞在指定的條件下的每一個線程。但是,線程能夠在調用子例程返回后即開始等待相同的條件。
#include <pthread.h>//定義條件變量 pthread_cond_t cond;//初始化條件變量 int pthread_cond_init (pthread_cond_t *cond, const pthread_condattr_t *attr) //cond:事先定義好的條件變量指針 //attr:事先定義好的條件變量屬性(默認NULL)//等待 1)調用時:解除鎖,等待條件變量,然后阻塞 2)返回時:收到信號,再次鎖定 int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex); //cond:初始化后的條件變量 //mutex:綁定的互斥量//定時等待 int pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *timeout);//發送信號 int pthread_cond_signal (pthread_cond_t *condition);//銷毀條件變量 int pthread_cond_destroy (pthread_cond_t *cond)示例:
#include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<pthread.h> #include<stdbool.h>void *thread_function1(void *arg); void *thread_function2(void *arg); pthread_mutex_t count_mutex; pthread_cond_t count_threshold_cv; bool ready = false; char msg1[] = "this is thread 1"; char msg2[] = "this is thread 2"; int main() {pthread_t thread1;pthread_t thread2;pthread_mutex_init(&count_mutex, NULL);pthread_cond_init (&count_threshold_cv, NULL);pthread_create(&thread1, NULL, thread_function1, (void *)msg1);pthread_create(&thread2, NULL, thread_function2, (void *)msg2);printf("waiting for thread to finish...\n");pthread_join(thread1, NULL);pthread_join(thread2, NULL);pthread_mutex_destroy(&count_mutex);pthread_cond_destroy(&count_threshold_cv);return 0; }void *thread_function1(void *arg) {printf("Tips:%s\n", (char *)arg);pthread_mutex_lock(&count_mutex);while (false == ready){pthread_cond_wait(&count_threshold_cv, &count_mutex);printf("thread1 in pthread_cond_wait\n");}if(true == ready)printf("now ready = true in thread1.\n");pthread_mutex_unlock(&count_mutex);pthread_exit(0); }void *thread_function2(void *arg) {sleep(3);printf("Tips:%s\n", (char *)arg);pthread_mutex_lock(&count_mutex);ready = true;printf("thread2 set ready = true\n");pthread_mutex_unlock(&count_mutex);pthread_cond_signal(&count_threshold_cv);pthread_exit(0); }判斷條件狀態的時候ready==false放在了while循環中,而不是if中,這是因為pthread_cond_wait()阻塞在條件變量上的時候,即使其他的線程沒有就該條件變量發出通知(pthread_cond_signal()/pthread_cond_broadcast()),條件變量也有可能會自己醒來(pthread_cond_wait()函數返回),因此需要重新檢查一下共享變量上的條件成不成立,確保條件變量是真的收到了通知,否則繼續阻塞等待。關于虛假喚醒的相關介紹,可以戳這里查看維基百科下面的幾個引用:https://en.wikipedia.org/wiki/Spurious_wakeup。
轉載于:https://www.cnblogs.com/wuxubj/p/10805386.html
總結
                            
                        - 上一篇: 原神反雷电将军特训怎么做?
 - 下一篇: 想知道华为手机录屏怎么操作