第七天 Thread(執行緒)--下
今天繼續來講執行緒,這麼多的thread程式設計者能透過執行緒庫所提供的API來管理及創建。而有兩種主要的方式來實做執行緒庫,一種是直接存在user space中,另外一種則是存在kernel space中,由作業系統來支持調配。目前主要使用的多執行緒庫有:Pthreads、Win32 threads跟Java threads,這裡我們只說Pthreads跟Java threads。
Pthreads是由IEEE 1003.1c的標準來定義創建的和操作執行緒的API。他可以提供給user-level或是kernel-level,而且他是一種定義並不是實作。
Java threads是由JVM所管理的,而他用什麼模型來實做,完全是看作業系統給他什麼樣的thread。Java threads的創建有兩種:繼承thread類別或是用Runnable interface產生間接的thread。
那隨著越來越多的thread產生,要能同步會比較困難,那我們就會運用到implicit thread。Implicit thread是由compiler(編譯器)跟run-time libraries來做。那有三種方法來實行:thread pools、OpenMP跟Grand Central Dispatch。
thread pools是一個存放等待被叫去工作的thread的地方,使用率很高。使用它有幾點好處:
OpenMP是由compiler來做,提供平行運作在shared-memory的環境中,而且定義平行區域內,哪個code能平行執行。
Grand Central Dispatch是apple的方法,容許識別平行的部分,而且在做thread時,可以不用處理那麼多的事情。Compiler會分割block內的資料到dispatch queue,這樣就可以同步執行。dispatch queue有兩種型態:serial跟concurrent。
Serial就是先送先處理(FIFO原理),像是main queue。Concurrent則是可以同時進行,不用照順序。
那thread還有一些議題我們可以討論:
fork()跟exec() system call語義:
當thread要被創建時,會運用fork() system call,這時就會看系統是要單一創建被互叫的thread,還是把所有的thread都複製出來。
用exec() system call的話,就會執行process中所有的thread。
訊號(signal)的處理:
Signal對UNIX來說是一個重要的機制,用來通知process抹些事件的發生。會有signal handler來管理這些signal,而signal會生成生是因為被某些特定的事件觸發而產生的。signal handler有兩種處理方式:default或是使用者自己定義。
單一個執行緒時,訊號會直接由process處理,如果是多重執行緒時,毀有以下幾種方式處理:
執行緒的取消:
在執行緒完成前,就把它結束掉,而這個被結束掉的thread,我們叫它target thread。提早結束的方式有三種,asynchronous cancellation、deferred cancellation跟actual cancellation。
asynchronous cancellation是當下說取消就取消; deferred cancellation則是等到他執行到一個週期後才取消掉; actual cancellation會看現在thread是什麼狀態,如果是disabled就要等到enabled時才能取消掉。
執行緒自己的儲存庫:
每一個執行緒都准許擁有自己的儲存庫(Thread-Local Storage ,TLS),對thread來說是獨一無二的,不會影響到其他thread的資料。他跟local variable不同的是他可以被自己以外的function看到,就像static一樣。
排程的啟動:
LWP (lightweight process),在user thread跟kernel thread中間的資料結構(中介程式),提供虛擬的process做排程,每個LWP都會跟kernel thread做連結。在溝通的機制中,排程的啟動會提供向上呼叫(upcall)的功能,從kernel 到thread library的upcall handler,這個溝通讓程式能維持正確的kernel thread數量。
我們來以作業系統舉例:
在windows中,一個thread有:
Thread主要的資料結構有以下幾種:
在Linux中,thread被稱為tasks。Thread的產生是由clone() system call執行,而非fork()。而task生成後,允許跟parent task(process)分享address space。