進程和線程 概念:在Linux中,線程一般被認為是“輕量級的進程”,進程是一個應用程式獨立運行單位,而線程不能獨立存在,必須由在一個進程建立. 線程相對進程的優點:
記憶體資料共用(1.進程需要獨立佔用各個段運行,線程可以多個同時在一個進程運行,共用同一記憶體;2.資料通用,效率高)
提高響應速度
cpu系統更有效,因為線程會運行在不同cpu
改善了程式結構,因為一個進程分化為多個線程,單獨線程可管理
實現基本函數
基本編程
常用線程函數
pthread_attr_init 初始化線程屬性 (要在create前初始化)
pthread_create 建立一個線程
pthead_exit 線程自行退出(exit(0)函數時退出進程)
pthread_join 其它線程等待某一個線程退出(釋放相關記憶體資源)
//線程結束後不能自動釋放記憶體,所以要用函數釋放
pthread_detach 使得子線程本身自己有自我回收記憶體資源的能力
pthread_cancel 當前線程將殺死其他的線程
pthread_self 獲得當前線程的標誌
具體函數
線程建立
函數原型是:
int pthread_create(pthread_t* thread,
pthread_attr_t* attr,
void (*start_routine)(void),
void * arg);
第一個參數是pthread_t類型的指標,這個指標指向用來存放當線程建立成功後的所建立的線程的標誌
第二個參數表明被建立的線程可以擁有的屬性
第三個參數是一函數指標,此函數指標指向線程的實現函數
第四個參數arg是void *類型的,此參數指向實際線程處理函數執行的時候所需要的參數 線程退出
線程的退出有兩種方式:
線程函數運行結束,比如到函數結尾或用return退出.線程自然結束.這是最常用的方式
可以顯式的調用pthread_exit()結束線程執行
函數原型是:
void pthread_exit(void*retval);
參數是指向線程的傳回值
線程的退出不能簡單使用exit()函數,因為一旦使用了exit()函數,實際上是整個進程的退出,會導致其他線程也隨著進程的消亡而消亡 等待線程退出
線程建立完畢後,建立線程的線程,就可以使用pthread_join() 函數等待被建立的線程的結束。pthread_join()函數會掛起建立線程的線程的執行,直到等待到想要等待的子線程
函數原型:
int pthread_join(pthread_t th, void **thread_return);
第一個參數th是需要等待的線程的標誌
如果thread_return不為空白,那麼thread_return指向th返回的值
調用pthread_join()函數的目的是釋放相關記憶體資源 線程分離
使得子線程本身自己有自我回收記憶體資源的能力
函數原型:
int pthread_detach(pthread_t th);
這個函數的目的是讓線程th可以處於分離(detached)狀態
處於分離狀態的線程有能力在自己結束執行的時候回收相關的記憶體資源
當前線程標誌
使用pthread_self()函數可以獲得當前線程的標誌
函數原型:
pthread_t pthread_self(void); 線程的撤消
一個線程可以通過向另個線程發送“請求”來結束另一個線程的執行。pthread_cancel()函數可以完成這個功能。
函數原型:
pthread_cancel(pthread_t thread)
當前線程將殺死線程ID為thread的線程
pthread_exit()是當前線程自已退出,而pthread_cancel是其它線程殺死別的線程 實現代碼
//有bug#include <stdio.h>#include <stdlib.h>#include <string.h>#include <pthread.h>void *Helloworld(void *arg){ int i=1; while(1) { printf("==Hello=="); if(i==3){ //線程退出1 pthread_exit(NULL); } //退出整個**進程** exit(0); } //線程退出2 return NULL;}int main(int argc, char *argv){ int i; pthread_t tid; //線程建立 if(pthread_create(&tid, NULL, Helloworld, NULL) != 0){ printf("==fail =="); return -1; } printf("==main=="); for(i=1; i<5; i++) { printf("!==main=="); } return 0;
步驟
1.建立.c檔案#touch m_pthread.c
2.編輯#vi m_pthread.c
3.連結#gcc -o fred m_pthread.c -lpthread
4.執行#./fred
pthread線程庫的使用
glib庫內建了線程庫.
在源碼中使用標頭檔 pthread.h
用gcc連結時加上 –lpthread 選項,連結線程庫 線程互斥(Mutex)
同步和互斥區別:
同步:一個執行,另一個相應執行(一起執行)
互斥:一個執行,另一個等待它執行完成才可以執行(單個單個執行) mutex作用:用來保護並發讀寫操作中的共用的資料結構,實際上用mutex可以用來實現臨界代碼區,本身狀態只有鎖定和非鎖定狀態
特性:
原子性:一個線程進行mutex操作,其他不能對同一個mutex操作
單一性:擁有mutex的一個線程除非釋放它,否則其他線程不能擁有
非忙等待:等待解鎖才可使用此mutex
mutex基本函數
死結:停在某個地方不運行
int pthread_mutex_init
int pthread_mutex_lock
int pthread_mutex_trylock
int pthread_mutex_unlock
int pthread_mutex_destroy 線程的同步
條件變數是線程的同步裝置
- 基本函數
pthread_cond_t cond= PTHREAD_COND_INITIALIZER;
int pthread_cond_init 初始化條件變數
int pthread_cond_signal 啟動等待cond指向的條件變數的一個線程
int pthread_cond_broadcast 啟動所有的等待條件變數的線程
int pthread_cond_wait 原子性地解鎖其第二個參數指向的mutex,然後等待條件變數條件的滿足
int pthread_cond_timedwait 在規定的時間內等待條件的滿足
int pthread_cond_wait 無限等待
int pthread_cond_destroy 釋放條件變數所佔的資源 訊號量
POSIX 訊號量在多線程編程中可以起到同步或互斥的作用。用POSIX 訊號量可以實現傳統作業系統P(通過)、V(釋放)操作
對POSIX訊號量的操作函數有:
int sem_init 初始化訊號量
int sem_wait 阻塞當前線程的執行
int sem_trywait
int sem_post sem指向的訊號量計數加1,相當於V 操作
int sem_getvalue 得到當前訊號量的值
int sem_destroy 釋放訊號量資源