文章目錄
- 進程和線程(續)
- 線程
- 1.線程傳參
- 2.線程屬性
- 3.線程間通信
- 1.概念
- 2.方式
- 3.互斥鎖
- 4.死鎖
- 5.信號量
- 習題
進程和線程(續)
線程
1.線程傳參
-
使用第四個參數實現對線程內部的傳參
代碼實現:
#include <stdio.h> #include <string.h> #include <dirent.h> #include <sys/types.h> #include <pthread.h> #include <unistd.h>typedef struct pthread_arg{pthread_t tid;char threadname[32];int sleeptime; }pthread_arg_t;void *thread(void *arg){pthread_arg_t *parg = arg;printf("%s(TID:%#lx)開始執行\n",parg->threadname,parg->tid);while(1){printf("%s正在執行\n",parg->threadname);sleep(parg->sleeptime);}return NULL; }int main(void){int i = 0;pthread_arg_t args[4] = {{0,"采集線程", 1},{0, "存儲線程", 2},{0, "顯示線程", 5},{0, "日志線程", 10}};for(i = 0;i < 4;i++){pthread_create(&args[i].tid,NULL,thread,&args[i]);}for(i = 0;i < 4;i++){pthread_join(args[i].tid,NULL);}return 0; }
2.線程屬性
- 加入屬性:線程結束需要pthread_join手動回收,但是可以完成線程間同步
- 分離屬性:線程結束后系統自動回收線程空間
-
pthread_attr_init
原型:int pthread_attr_init(pthread_attr_t *attr); 功能:線程屬性初始化 參數:attr:線程屬性空間的首地址
-
pthread_attr_setdetachstate
原型:int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate); 功能:將線程屬性設置為分離屬性 參數:attr:線程屬性空間的首地址detachstate:屬性PTHREAD_CREATE_DETACHED 分離屬性PTHREAD_CREATE_JOINABLE 加入屬性
-
pthread_attr_destroy
原型:int pthread_attr_destroy(pthread_attr_t *attr); 功能:線程屬性銷毀 參數:attr:線程屬性空間的首地址
3.線程間通信
1.概念
- 多個線程間傳遞信息
2.方式
采用全局變量
- 原因:進程是操作系統分配的最小單元;每個進程空間獨立,包含文本段,數據段(全局變量),系統數據段;一個進程中的多個線程獨享棧空間,而文本段,數據段,堆區進程多線程共享
- 多線程同時操作共享空間會引發資源競爭,需要加上互斥鎖解決資源競爭問題
3.互斥鎖
-
概念
-
解決資源競爭的一種方式,可以看成是一種資源
-
只能加鎖一次,加鎖期間不能再次加鎖,也不能強制占有一個已經加鎖的鎖資源,必須等待鎖資源釋放,也就是解鎖后才能繼續操作該鎖
-
加鎖和解鎖中間的代碼稱為臨界代碼,也稱為臨界區
-
只能防止多個線程對資源的競爭,不能決定代碼的先后執行順序
-
原子操作:CPU執行原子操作時無法切換調度任務
-
-
使用方式
- 定義互斥鎖
- 對鎖初始化
- 操作全局資源前先加鎖
- 如果加鎖成功則完成對全局資源操作
- 如果加鎖失敗則表示有人占用資源,必須等待其余人釋放鎖資源才能加鎖成功
- 直到加鎖成功使用該全局資源
-
函數接口
-
pthread_mutex_init
原型:int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr); 功能:初始化互斥鎖 參數:mutex:互斥鎖空間首地址attr:屬性,默認為NULL 返回值:成功返回0失敗返回-1
-
pthread_mutex_lock
原型:int pthread_mutex_lock(pthread_mutex_t *mutex); 功能:互斥鎖加
-
pthread_mutex_unlock
原型:int pthread_mutex_unlock(pthread_mutex_t *mutex); 功能:互斥鎖解
-
pthread_mutex_destroy
原型:int pthread_mutex_destroy(pthread_mutex_t *mutex); 功能:互斥鎖銷毀
-
4.死鎖
- 概念
- 多線程由于加鎖解鎖不合理導致程序無法繼續向下運行的狀態
- 產生的條件
- 互斥條件
- 不可剝奪條件
- 請求保持條件
- 循環等待條件
- 避免死鎖
- 加鎖順序保持一致
- 使用pthread_mutex_trylock替換pthread_mutex_lock
5.信號量
-
概念
- 信號量是一種資源
- 信號量只能完成初始化,銷毀,申請,釋放四種操作
- 如果信號量資源數為0,申請資源會阻塞等待,直到占用資源的任務釋放資源,資源數不為0時才能申請到資源并繼續向下執行
- 釋放資源不會阻塞
-
函數接口
-
sem_init
原型:int sem_init(sem_t *sem, int pshared, unsigned int value); 功能:初始化信號量 參數:sem:信號空間首地址pshared:0:一個進程的多個線程間共享!0:多個進程間共享value:初始化的資源的值 返回值:成功返回0失敗返回-1
-
sem_destroy
原型:int sem_destroy(sem_t *sem); 功能:銷毀信號量 參數:sem:信號量空間的首地址 返回值:成功返回0失敗返回-1
-
sem_wait
原型:int sem_wait(sem_t *sem); 功能:申請信號量 參數:sem:信號量空間的首地址 返回值:成功返回0失敗返回-1
- 申請信號量會使信號量資源數為-1
- 如果信號量資源數為0,則會阻塞等待,直到有任務釋放資源,才能拿到資源并繼續向下執行
-
sem_post
原型:int sem_post(sem_t *sem); 功能: 釋放信號量 參數: sem:信號量空間首地址 返回值: 成功返回0 失敗返回-1
-
習題
編寫三個線程任務,線程一循環打印‘A’,線程一循環打印‘B’,線程一循環打印‘C’,要求打印出的字符順序總為ABC
代碼實現:
#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
#include<stdlib.h>
#include<semaphore.h>sem_t sem_wa;
sem_t sem_wb;
sem_t sem_wc;void *thread1(void *arg){while(1){sem_wait(&sem_wa);printf("A\n");sem_post(&sem_wb);}return NULL;
}
void *thread2(void *arg){while(1){sem_wait(&sem_wb);printf("B\n");sem_post(&sem_wc);}return NULL;
}
void *thread3(void *arg){while(1){sem_wait(&sem_wc);printf("C\n");sem_post(&sem_wa);}return NULL;
}int main(void){pthread_t tid1;pthread_t tid2;pthread_t tid3;sem_init(&sem_wa,0,1);sem_init(&sem_wb,0,0);sem_init(&sem_wc,0,0);pthread_create(&tid1,NULL,thread1,NULL);pthread_create(&tid2,NULL,thread2,NULL);pthread_create(&tid3,NULL,thread3,NULL);pthread_join(tid1,NULL);pthread_join(tid2,NULL);pthread_join(tid3,NULL);sem_destroy(&sem_wa);sem_destroy(&sem_wb);sem_destroy(&sem_wc);return 0;
}