Linux多线程编程(一)---多线程基本编程
版權聲明:本文為博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/mybelief321/article/details/9377379
線程概念
? ? 線程是指運行中的程序的調度單位。一個線程指的是進程中一個單一順序的控制流,也被稱為輕量級線程。它是系統獨立調度和分配的基本單位。同一進程中的多個線程將共享該系統中的全部系統資源,比如文件描述符和信號處理等。一個進程可以有很多線程,每個線程并行執行不同的任務。
線程與進程比較
? ?① ?和進程相比,它是一種非常“節儉”的多任務操作方式。在Linux系統中,啟動一個新的進程必須分配給它獨立的地址空間,建立眾多的數據表來維護其代碼段、堆棧段和數據段,這種多任務工作方式的代價非?!鞍嘿F”。而運行于一個進程中的多個線程,它們彼此之間使用相同的地址空間,共享大部分數據,啟動一個線程所花費的空間遠遠小于啟動一個進程所花費的空間,而且線程間彼此切換所需要時間也遠遠小于進程間切換所需要的時間。
? ?② ?線程間方便的通信機制。對不同進程來說它們具有獨立的數據空間,要進行數據的傳遞只能通過通信的方式進行。這種方式不僅費時,而且很不方便。線程則不然,由于同一進程下的線程之間共享數據空間,所以一個線程的數據可以直接為其他線程所用,不僅方便,而且快捷。
線程基本編程
? ?Linux系統下的多線程遵循POSIX線程接口,稱為pthread。編寫Linux下的多線程程序,需要使用頭文件pthread.h,連接時需要使用庫libpthread.a。因為pthread的庫不是Linux系統的庫,所以在編譯時要加上 -lpthread。例如:gcc ?filename ?-lpthread。注意,這里要講的線程相關操作都是用戶空間中的線程的操作。
? ?線程創建:創建線程實際上就是確定調用該線程函數的入口點,這里通常使用的函數是pthread_create()。在線程創建后,就開始運行相關的線程函數。
??
? 線程退出:在線程創建后,就開始運行相關的線程函數,在該函數運行完之后,該線程也就退出了,這也是線程退出的一種方法。另一種退出線程的方法是使用函數pthread_exit(),這是線程的主動行為。這里要注意的是,在使用線程函數時,不能隨意使用exit()退出函數來進行出錯處理。由于exit()的作用是使調用進程終止,而一個進程往往包含多個線程,因此,在使用exit()之后,該進程中的所有線程都終止了。在線程中就可以使用pthread_exit()來代替進程中的exit()。
??
? 線程等待:由于一個進程中的多個線程是共享數據段的,因此,通常在線程退出后,退出線程所占用的資源并不會隨著線程的終止而得到釋放。正如進程之間可以用wait()系統調用來同步終止并釋放資源一樣,線程之間也有類似機制,那就是pthread_join()函數。pthread_join()用于將當前進程掛起來等待線程的結束。這個函數是一個線程阻塞的函數,調用它的函數將一直等待到被等待的線程結束為止,當函數返回時,被等待線程的資源就被收回。
??
? 線程取消:前面已經提到線程調用pthread_exit()函數主動終止自身線程,但是在很多線程應用中,經常會遇到在別的線程中要終止另一個線程的問題,此時調用pthread_cancel()函數來實現這種功能,但在被取消的線程的內部需要調用pthread_setcancel()函數和pthread_setcanceltype()函數設置自己的取消狀態。例如,被取消的線程接收到另一個線程的取消請求之后,是接受函數忽略這個請求;如果是接受,則再判斷立刻采取終止操作還是等待某個函數的調用等。
??
? 線程標識符獲取:獲取調用線程的標識ID。
??
? 線程清除:線程終止有兩種情況:正常終止和非正常終止。線程主動調用pthread_exit()或者從線程函數中return都將使線程正常退出,這是可預見的退出方式;非正常終止是線程在其它線程的干預下,或者由于自身運行出錯(比如訪問非法地址)而退出,這種退出方式是不可預見的。不論是可預見的線程終止還是異常終止,都回存在資源釋放的問題,如何保證線程終止時能順利地釋放掉自己所占用的資源,是一個必須考慮的問題。
? 從pthread_cleanup_push()的調用點到pthread_cleanup_pop()之間的程序段中的終止動作(包括調用pthread_exit()和異常終止,不包括return)都將執行pthread_cleanup_push()所指定的清理函數。
??
? ?
實驗1
? ?功能:使用pthread_create()函數創建線程的實例
? ?代碼:thread_create.c文件
? ??
? ? ?
? ? 編譯:使用命令:gcc thread_create.c -o thread_create -lpthread編譯,注意不要忘了加 -lpthread,否則會出現如下的錯誤
/tmp/ccjfZIN3.o: In function `main':
thread_create.c:(.text+0x8b): undefined reference to `pthread_create'
thread_create.c:(.text+0xc0): undefined reference to `pthread_create'
thread_create.c:(.text+0xeb): undefined reference to `pthread_join'
thread_create.c:(.text+0xfc): undefined reference to `pthread_join'
collect2: ld returned 1 exit status
? ?執行:
? ?
實驗2
? 功能:使用pthread_exit()函數退出線程的舉例
? 代碼:thread_exit.c文件
? ? ?
? 編譯:gcc thread_exit.c -o thread_exit -lpthread
? 執行:./thread_exit
??
實驗3
? 功能:用pthread_join()實現線程等待。
? 代碼:thread_join.c文件
??
? 編譯:gcc thread_join.c -o thread_join -lpthread??
? 執行:./thread_join
??
?可以看出,pthread_join()等到線程結束后,程序才繼續執行。
實驗4
? 功能:使用pthread_self()獲取線程ID
? 代碼:thread_id.c文件
??
? 編譯:gcc thread_id.c -o thread_id -lpthread
? 執行:./thread_id
??
實驗5
? 功能:線程清理函數的使用
? 代碼:thread_clean.c
??
??
? ?
? ?注意,在編寫的代碼的時候,自己修改一下傳遞的參數和clean_pop函數的參數,相信你會更有收獲。
? 編譯:gcc thread_clean.c -o thread_clean -lpthread
? 執行:./thread_clean
? ?
實驗6
? 功能:本實驗創建了3個進程,為了更好的描述線程之間的并行執行,讓3個線程共用同一個執行函數。每個線程都有5次循環(可以看成5個小任務),每次循環之間會隨機等待1~10s的時間,意義在于模擬每個任務的到達時間是隨機的,并沒有任何特定的規律。
? 代碼:thread.c文件,該代碼文件點此下載
??
??
? 編譯:gcc thread.c -o thread -lpthread
? 執行:./thread
? ??
? 從實驗結果可以看出,線程執行的順序雜亂無章的,看著就頭疼,下一節就利用線程之間的同步與互斥機制處理此文件http://blog.csdn.net/mybelief321/article/details/9390707
總結
以上是生活随笔為你收集整理的Linux多线程编程(一)---多线程基本编程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 可以在没有main()的情况下编写C程序
- 下一篇: 如何利用循环代替递归以防止栈溢出(译)