有關多執行緒的一些技術問題

2021-09-08 21:06:37 字數 3284 閱讀 5161

有關多執行緒的一些技術問題:

1、  何時使用多執行緒?

2、  執行緒如何同步?

3、  執行緒之間如何通訊?

4、  程序之間如何通訊?

先來回答第乙個問題,執行緒實際主要應用於四個主要領域,當然各個領域之間不是絕對孤立的,他們有可能是重疊的,但是每個程式應該都可以歸於某個領域:

1、  offloading time-consuming task。由輔助線程來執行耗時計算,而使gui有更好的反應。我想這應該是我們考慮使用執行緒最多的一種情況吧。

2、  scalability。伺服器軟體最常考慮的問題,在程式中產生多個執行緒,每個執行緒做乙份小的工作,使每個cpu都忙碌,使cpu(一般是多個)有最佳的使用率,達到負載的均衡,這比較複雜,我想以後再討論這個問題。

3、  fair-share resource allocation。當你向乙個負荷沉重的伺服器發出請求,多少時間才能獲得服務。乙個伺服器不能同時為太多的請求服務,必須有乙個請求的最大個數,而且有時候對某些請求要優先處理,這是執行緒優先順序幹的活了。

4、  simulations。執行緒用於**測試。

我把主要的目光放在第乙個領域,因為它正是我想要的。第二和第三個領域比較有意思,但是目前不在我的研究時間表中。

執行緒的同步機制:

1、  event

用 事件(event)來同步執行緒是最具彈性的了。乙個事件有兩種狀態:激發狀態和未激發狀態。也稱有訊號狀態和無訊號狀態。事件又分兩種型別:手動重置事件 和自動重置事件。手動重置事件被設定為激發狀態後,會喚醒所有等待的執行緒,而且一直保持為激發狀態,直到程式重新把它設定為未激發狀態。自動重置事件被設 置為激發狀態後,會喚醒「乙個」等待中的執行緒,然後自動恢復為未激發狀態。所以用自動重置事件來同步兩個執行緒比較理想。mfc中對應的類為 cevent.。cevent的建構函式預設建立乙個自動重置的事件,而且處於未激發狀態。共有三個函式來改變事件的狀 態:setevent,resetevent和pulseevent。用事件來同步執行緒是一種比較理想的做法,但在實際的使用過程中要注意的是,對自動重 置事件呼叫setevent和pulseevent有可能會引起死鎖,必須小心。

2、  critical section

使用 臨界區域的第乙個忠告就是不要長時間鎖住乙份資源。這裡的長時間是相對的,視不同程式而定。對一些控制軟體來說,可能是數毫秒,但是對另外一些程式來說, 可以長達數分鐘。但進入臨界區後必須盡快地離開,釋放資源。如果不釋放的話,會如何?答案是不會怎樣。如果是主線程(gui執行緒)要進入乙個沒有被釋放的 臨界區,呵呵,程式就會掛了!臨界區域的乙個缺點就是:critical section不是乙個核心物件,無法獲知進入臨界區的執行緒是生是死,如果進入臨界區的執行緒掛了,沒有釋放臨界資源,系統無法獲知,而且沒有辦法釋放該臨 界資源。這個缺點在互斥器(mutex)中得到了彌補。critical section在mfc中的相應實現類是ccriticalsection。ccriticalsection::lock()進入臨界 區,ccriticalsection::unlock()離開臨界區。

3、  mutex

互斥器的功能和臨界區域很相似。區別 是:mutex所花費的時間比critical section多的多,但是mutex是核心物件(event、semaphore也是),可以跨程序使用,而且等待乙個被鎖住的mutex可以設定 timeout,不會像critical section那樣無法得知臨界區域的情況,而一直死等。mfc中的對應類為cmutex。win32函式有:建立互斥體createmutex() ,開啟互斥體openmutex(),釋放互斥體releasemutex()。mutex的擁有權並非屬於那個產生它的執行緒,而是最後那個對此 mutex進行等待操作(waitforsingleobject等等)並且尚未進行releasemutex()操作的執行緒。執行緒擁有mutex就好像 進入critical section一樣,一次只能有乙個執行緒擁有該mutex。如果乙個擁有mutex的執行緒在返回之前沒有呼叫releasemutex(),那麼這個 mutex就被捨棄了,但是當其他執行緒等待(waitforsingleobject等)這個mutex時,仍能返回,並得到乙個 wait_abandoned_0返回值。能夠知道乙個mutex被捨棄是mutex特有的。

4、  semaphore

訊號量 是最具歷史的同步機制。訊號量是解決producer/consumer問題的關鍵要素。對應的mfc類是csemaphore。win32函式 createsemaphore()用來產生訊號量。releasesemaphore()用來解除鎖定。semaphore的現值代表的意義是目前可用 的資源數,如果semaphore的現值為1,表示還有乙個鎖定動作可以成功。如果現值為5,就表示還有五個鎖定動作可以成功。當呼叫wait…等函式要 求鎖定,如果semaphore現值不為0,wait…馬上返回,資源數減1。當呼叫releasesemaphore()資源數加1,當時不會超過初始 設定的資源總數。

執行緒之間的通訊:

執行緒常常要將資料傳遞給另外乙個執行緒。worker執行緒可能需要告訴別人說它的工作完成了,gui執行緒則可能需要交給worker執行緒一件新的工作。

通 過postthreadmessage(),可以將訊息傳遞給目標執行緒,當然目標執行緒必須有訊息佇列。以訊息當作通訊方式,比起標準技術如使用全域性變數 等,有很大的好處。如果物件是同一程序中的執行緒,可以傳送自定義訊息,傳遞資料給目標執行緒,如果是執行緒在不同的程序中,就涉及程序之間的通訊了。下面將會 講到。

程序之間的通訊:

當執行緒分屬於不同程序,也就是分駐在不同的位址空間時,它們之間的通訊需要跨越位址空間的邊界,便得採取一些與同一程序中不同執行緒間通訊不同的方法。

2、  wm_copydata效率上面不是太高,如果要求高效率,可以考慮使用共享記憶體(shared memory)。使用共享記憶體要做的是:設定一塊記憶體共享區域;使用共享記憶體;同步處理共享記憶體。

第二步:使用共享記憶體。共享記憶體指標的使用是一件比較麻煩的事,我們需要借助_based屬性,允許指標被定義為從某一點開始起算的32位偏移值。

第四步:同步處理。可以借助mutex來進行同步處理。

3、  ipc

1)anonymous pipes。anonymous pipes只被使用於點對點通訊。當乙個程序產生另乙個程序時,這是最有用的一種通訊方式。

2)named pipes。named pipes可以是單向,也可以是雙向,並且可以跨越網路,步侷限於單機。

3)mailslots。mailslots為廣播式通訊。server程序可以產生mailslots,任何client程序可以寫資料進去,但是只有server程序可以取資料。

4)ole automation。ole automation和udp都是更高階的機制,允許通訊發生於不同程序間,甚至不同機器間。

5)dde。dde動態資料交換,使用於16位windows,目前這一方式應盡量避免使用。

一些多執行緒的筆記

1.保護方法原子性的同時,也要注意保護方法中使用到的變數。下面這段 是否一定安全?public class counter public synchronized void add1 other method 不一定,如果在other method中也處理counter但是又沒有保護的情況下,會出現...

做港台專案開發遇到的一些非技術問題總匯。。。

乙個小專案,差不多是乙個單使用者個人部落格的性質。技術上沒什麼說的,都差不多。現在就是說一下開發後的問題。伺服器是乙個虛擬空間,作業系統是server 2003,web發布不是iis,而是乙個叫 abyss web server 的工具,支援asp.net2.0的應用。語言包是正體中文。客戶要求英文...

有關技術管理的一些思考

這些天裡工作的環境發生了一些微小的變化,可能以後對基層開發的程式設計師也會有更加具體的影響。上週參加 open party 時,重點聽了 那些失敗的專案們 分析了乙個專案的提出 實施,直到最後失敗的過程。我也在想乙個技術團隊究竟應該用怎樣的一種管理方式,才能讓技術團隊的效率達到更優。我分了幾個小主題...