APUE學習 執行緒(1)

2021-06-20 20:29:38 字數 4030 閱讀 4276

執行緒(thread)----輕量級的程序、cpu排程的最小單位,相比較於程序,程序是分配資源的最小單位。

之前講到的是多程序程式設計,這一部分要說的是如何在乙個程序中實現多執行緒程式設計(當然將程序部分的內容放到一起,就可以實現多程序多執行緒程式設計)。posix(可移植性作業系統介面)規定了可移植性的執行緒庫pthread庫,這裡面的函式需要在編譯時加上-lpthread(-pthread)引數,pthread庫中的型別以及函式是不透明的(掌握如何使用,無須關心如何實現)。

乙個程序中至少有乙個執行緒,從main()開始執行的執行緒稱為 主線程(初始執行緒)。執行緒id型別pthread_t,可以使用pthread_self()返回,需要注意的是,執行緒id只是在乙個程序內有效(程序id在整個系統中有效);使用pthread_equal()比較兩個執行緒的id是否相等。

[cpp]view plain

copy

pthread_t pthread_self(

void

);  

intpthread_equal(pthread_t tid1, pthread_t tid2);  

執行緒建立的建立使用pthread_create()函式:

[cpp]view plain

copy

intpthread_create(pthread_t *tidp, 

const

pthread_attr_t *attr, 

void

*(*start_rtn)(

void

*), 

void

*arg);  

函式的第乙個引數tidp,是乙個出參,用來帶回被建立執行緒的tid;第二個引數attr設定的執行緒屬性(後面說明),預設屬性傳null即可;第三個引數start_rtn是乙個函式指標,是被建立執行緒的入口函式(新執行緒從該函式開始執行至該函式結束);第四個引數arg是start_rtn函式的引數;該函式呼叫成功返回0,否則返回出錯編碼(不使用errno全域性變數)。幾點需要注意:

1.受os排程影響,被建立的執行緒處於就緒狀態,故建立執行緒的執行緒往往是先被呼叫。

2.同一程序中的多個執行緒共享記憶體資源,故多個執行緒對程序中的所有變數都是共享的(但要注意該變數的生存期和作用域)。

3.只要程序(主線程)退出,其餘未結束的執行緒都隨之結束了(程序結束資源也就沒了)

4.同一程序中的多個執行緒共享檔案描述符,並非複製乙份。

5.同一程序中的多個執行緒共享程序的訊號遮蔽字,但新執行緒的未決訊號集講被清空。

程序退出的方式:從start_rtn返回;自身呼叫pthread_exit()函式;被同乙個程序中的其他執行緒取消。先來看pthread_exit()函式和與之配套的pthread_join()函式:

[cpp]view plain

copy

void

pthread_exit(

void

*rval_ptr);  

intpthread_join(pthread_t 

thread

, void

**rval_ptr);  

pthread_exit()函式類似於程序中的exit()函式,執行緒直接終止,並將rval_ptr引數作為執行緒的返回值。pthread_join()的功能類似程序的waitpid(pid)函式,阻塞等待指定的執行緒退出並接受返回值,引數是void **型別,是乙個出參引數。

執行緒中也有類似程序atexit()註冊清理操作的函式,pthread_cleanup_push() pthread_cleanup_pop()註冊執行緒的清理函式。

[cpp]view plain

copy

void

pthread_cleanup_push(

void

(*rtn)(

void

*), 

void

*arg);  

void

pthread_cleanup_pop(

intexecute);  

註冊的函式有兩個引數,乙個是函式指標,乙個是該函式接收的引數。第二個函式在執行後會設定之前註冊的函式的執行狀態,如果execute為0則不執行否則執行,需要注意的是,這兩個函式必須是在乙個函式內成對出現(具體實現應該是帶括號的巨集定義),但可以考慮放到pthread_exit()後。

再來說下pthread_cancel()函式,它和pthread_exit()都能使乙個執行緒退出,不同是後者是使執行緒本身退出,而前者是使同一程序中的其他執行緒退出。

[cpp]view plain

copy

intpthread_cancel(pthread_t tid);  

該函式的原理是:向tid執行緒傳送sigcancel訊號(這個訊號在kill -l中查詢不到)。只是傳送乙個訊號作為請求,但指定的執行緒是否退出何時退出pthread_cancel()並不關心,這就涉及到乙個問題,乙個執行緒在接收到sigcancel訊號時何時退出,有個取消點的概念。大部分的pthread函式以及阻塞的系統呼叫都是取消點,增加設定取消點的函式是pthread_testcancel():

[cpp]view plain

copy

void

pthread_testcancel(

void

);  

通過這個函式可以設定取消點。取消點涉及到可取消狀態和取消型別的的概念,相關操作如下:

[cpp]view plain

copy

intpthread_setcancelstate(

intstate, 

int*oldstate);  

intpthread_setcanceltype(

inttype, 

int*oldtype);  

分別用來設定取消狀態和取消型別。取消狀態包括pthread_cancel_enbale可以被取消 pthread_cancel_disable不允許被取消;取消型別包括pthread_cancel_deferred直到取消點才終止 pthread_cancel_asynchronous立即終止(這個在很多平台下是不好用的)

再介紹一下其他的執行緒屬性,執行緒屬性的型別是pthread_attr_t型別,型別的初始化和銷毀分別是pthread_attr_init()  pthread_attr_destroy()兩個函式:

[cpp]view plain

copy

intpthread_attr_init(pthread_attr_t *attr);  

intpthread_attr_destroy(pthread_attr_t *attr);  

執行緒的屬性包括:分離屬性 繫結屬性 執行緒棧屬性等等,這裡我們只說下分離屬性(其餘的用不到)。如果乙個執行緒被分離了,那麼建立它的執行緒即使呼叫了pthread_join()也不能等待並接受該執行緒的返回值。設定分離屬性有兩種方法,第一種是直接呼叫pthread_detach()函式,第二個中是將執行緒屬性傳入到pthread_create()函式中。

[cpp]view plain

copy

intpthread_detach(pthread_t tid);  

intpthread_attr_getdetachstate(

const

pthread_attr_t * attr,  

int*detachstate);  

intpthread_attr_setdetachstate(pthread_attr_t *attr, 

intdetachstate);  

pthread_detach()函式使tid執行緒分離,後面兩個函式操作的是執行緒屬性的結構,detachstate的值可以是pthread_create_joinable不分離(預設的) pthread_create_detached分離。這兩種方法的區別是,第一種用於執行緒已被建立後分離,另一種用於建立前設定。

函式程序APUE學習 Posix執行緒 1

在寫這篇文章之前,已經寫過了幾篇關於改函式程序主題的文章,想要了解的朋友可以去翻一下之前的文章 執行緒 thread 輕量級的程序 cpu排程的最小單位,相比較於程序,程序是分配資源的最小單位。之前講到的是多程序程式設計,這一部份要說的是如安在乙個程序中實現多執行緒程式設計 當然將程序部份的內容放到...

APUE學習筆記 執行緒

採用多執行緒模式可以採用同步程式設計,而非非同步程式設計,可以簡化程式設計 多個程序間可以很方便的共享資料 可以通過pthread self獲得自身的執行緒id。執行緒id只在程序內部唯一。新建立執行緒不能保證那個執行緒先執行,新縣城可以訪問程序的位址空間,繼承執行緒的浮點環境和訊號遮蔽字。如果任意...

APUE筆記(1) 配置APUE環境

本人用的是centos6.5版本的linux 寫這個環境配置是因為自己這一天被這個環境配置給搞的很難受 首先,我們在linux下找乙個資料夾,存放apue3的包 cd home src wget 然後解壓 tar zxv f src.3e.tar.gz 進入apue.3e資料夾 cd home sr...