1. 程式人生 > >C++多執行緒程式設計學習

C++多執行緒程式設計學習

1、執行緒的基本概念、執行緒的基本狀態及狀態之間的關係。

(1)執行緒的概念 

-------1) 執行緒最直接的理解就是“輕量級程序”,它是一個基本的CPU執行單元,也是程式執行流的最小單位,由執行緒ID、程式計數器、暫存器集合和堆疊組成。 

-------2) 執行緒是程序中的一個實體,是被系統獨立排程和分派的基本單位。執行緒自己不擁有系統資源,只擁有一點在執行中必不可少的資源,但它可以與同屬一個程序的其它執行緒共享程序所擁有的全部資源。

-------3)不同的執行緒可以執行相同的程式,即同一個服務被不同的使用者呼叫時,作業系統為它們建立成不同的執行緒。

-------4)執行緒是處理機的獨立排程單位,多個執行緒是可以併發執行的。在單CPU的計算機系統中,各執行緒可以交替的佔用CPU,在多CPU的計算機系統中,各執行緒可以同時佔用不同的CPU,若各個CPU同時為一個程序內的各執行緒服務則可縮短程序的處理週期。

(2)執行緒的基本狀態

執行緒也有就緒、阻塞和執行三種狀態。

執行狀態表示執行緒正在獲得處理機而執行

就緒狀態指執行緒已具備了各種執行條件,一旦獲得CPU便可執行的狀態

阻塞狀態指執行緒在執行中因某事件而受阻,處於暫停執行的狀態。

2、執行緒與程序的區別

1)排程

在傳統的作業系統中,擁有資源和獨立排程的基本單位都是程序。在引入執行緒的作業系統中,執行緒是獨立排程的基本單位,程序是擁有資源的基本單位。在同一程序中,執行緒的切換不會引起程序切換。在不同的程序中進行執行緒切換,如從一個程序內的執行緒切換到另一個程序中的執行緒時,會引起程序切換。

2)擁有資源

不論是傳統的作業系統還是擁有執行緒的作業系統,程序都是擁有資源的基本單位,而執行緒不擁有資源(只有一點必不可少的資源),但執行緒可以訪問其隸屬程序的系統資源。

3)併發性

在引入執行緒的作業系統中,不僅程序間可以併發執行,同一程序內的多個執行緒間也可以併發執行,從而使作業系統具有更好的併發性,提高了系統吞吐量。

4)系統開銷

由於建立或撤銷程序時,系統都要為之分配或回收資源,如記憶體空間、IO裝置等,因此作業系統所付出的開銷遠大於建立或撤銷執行緒時的開銷。類似的,進行程序切換時,涉及當前執行過程CPU環境的儲存及新排程到程序CPU環境的設定,而執行緒切換隻需要儲存和設定少量的暫存器內容,開銷很小。此外,由於同一程序內的多個執行緒共享程序的地址空間,因此,這些執行緒之間的同步與通訊非常容易實現,甚至無需作業系統的干預。

5)地址空間和其它資源

程序的地址空間相互獨立,同一程序的各執行緒共享程序的資源,而程序內的執行緒對其它程序不可見。

6)通訊方面

程序間通訊(IPC)需要程序同步和互斥手段的輔助,以保證資料的一致性,而執行緒間可以直接讀/寫程序資料段(如全域性變數)來進行通訊。

3、執行緒的同步與互斥

執行緒同步的方法主要有以下四種:

-------1)臨界區(Critical Section):通過臨界區實現多個執行緒對同一公共資源或一段程式碼的序列訪問,速度快,適合控制資料的訪問。    

      保證某一時刻只有一個執行緒訪問某一資源的簡便方法。任意時刻只允許一個執行緒對資源的訪問。如果同一時刻由多個執行緒試圖訪問臨界區,則其中一個執行緒進入臨界區後,其它執行緒將會被掛起等待,並一直持續到該執行緒退出臨界區。當臨界區被釋放後,其它執行緒可以搶佔,並以此達到原子方式操作共享資源的目的。

      臨界區的兩個原語:EnterCriticalSection() 進入臨界區;LeaveCriticalSection()退出臨界區。

-------2)互斥量(Mutex):通過協調執行緒共同對一個共享資源的單獨訪問而設計。 

      互斥量跟臨界區很相似,只有擁有互斥物件的執行緒才具有訪問資源的許可權。由於互斥物件只有一個,因此就決定了同時只有一個執行緒擁有對資源的訪問許可權。當前佔據資源的執行緒在任務處理完成後交付互斥物件,以便其它執行緒可以擁有該互斥物件實現對資源的控制訪問。互斥量比臨界區複雜,互斥量不僅可以實現同一應用程式的不同執行緒間的同步,而且可以實現不同程式間執行緒的對資源的安全共享。

      互斥量包含的幾個操作原語:

          CreateMutex()建立互斥量

          OpenMutex()開啟互斥量

          ReleaseMutex()釋放互斥量

          WaitForMultipleObjects() 等待互斥物件

-------3)訊號量(Semaphores):可以控制有限使用者對同一資源的的訪問而設計;

      訊號量對執行緒同步的方法與前幾種不同,訊號量允許多個執行緒同時使用共享資源,這與作業系統中的PV操作相同。它指出了同時訪問共享資源的最大執行緒數目。它允許多個執行緒在同一時刻訪問同一資源,但是限制了同一時刻訪問資源的最大執行緒數目。在用CreateSemaphore()建立訊號量時,要同時指出允許訪問的最大資源基數和當前可用資源計數。一般把當前可用資源計數作為最大資源計數,即每增加一個執行緒對資源的訪問相應的資源計數就會減一,只要當前可用資源計數是大於0的,就可以發出訊號量訊號。但是當前可用資源減小到小於0時,則說明當前佔用資源的執行緒數目已經達到最大,不允許執行緒的繼續進入,此時訊號量也無法發出。當執行緒處理完資源後,應該離開的同時通過ReleaseSemaphore()使資源計數加1。在任何時候當前可用資源數目不可用大於最大資源數目。

       PV操作是由荷蘭科學家提出的。訊號量S是一個整數,當S大於等於0時,代表可給併發程序使用的資源實體,但S小於零正在等待使用共享資源的數目。

       P操作申請資源:

         (1)S減1

         (2)若S減1後仍大於等於0,則程序繼續;

         (3)若S減1後小於0,則程序被阻塞後放入該訊號相應的佇列中,然後轉入程序排程;

       V操作釋放資源:

        (1)S加1操作;

        (2)若S加1後大於0,則程序繼續執行;

        (3)若S加1小於等於0,則從訊號量的等待佇列中喚醒一個等待程序,然後再返回原程序繼續執行或轉入程序排程。

      訊號量包含的幾個操作原語:

         CreateSemphore()建立一個訊號量;

         OpenSemphore()開啟一個訊號量;

         ReleaseSemaphore()退出一個訊號量;

         WaitForSingleObject()等待一個訊號量

------4)事件(Event):通過通知執行緒的有一些事件已經發生,從而可以啟動後續的任務執行。

      事件物件也可以通過通知操作的方式保持執行緒同步,可以實現不同程序中的執行緒同步操作;

總結:

      1)互斥量與臨界區的作用非常相似。但互斥量是可以命名的,也就是說可以擴程序使用,所以建立互斥所需的資源更多,所以如果為了在程序內部使用的話,可以通過臨界區來提高速度上的優勢,並且可以減少資源的使用。互斥量是跨程序的,一旦被建立就可以通過名字開啟。 

     2)互斥量、訊號量和事件都可以被跨越程序來進行程序同步資料操作,而其他的物件與資料同步操作無關,但對於程序和執行緒來講,如果程序和執行緒在執行狀態為無訊號狀態,在退出後為有訊號狀態。所以可以使用WaitForSingleObject來等待程序和執行緒退出。 

     3)通過互斥量可以指定資源獨佔的方式使用,但如果有下面一種情況,訊號量就無法處理,比如一個使用者購買了一份三個併發訪問許可的資料可系統,可以根據使用者購買的訪問許可數量來決定由多少個執行緒/程序能同時進行資料庫操作,這時候如果利用互斥量就沒有辦法完成請求,可以使用訊號量。

4、死鎖產生的原因以及如何避免死鎖

    產生死鎖的主要原因是

             1)系統資源不足

             2)程序執行推進的順序不合適

             3)資源分配不當

    產生死鎖的4個必要條件

             1)互斥條件:一個資源每次只能被一個程序使用

             2)請求與保持條件:一個程序因請求資源而被阻塞時,對已獲得的資源保持不放

             3)不剝脫條件:程序已獲得的資源在未使用完之前不被強行剝奪

             4)迴圈等待條件:若干程序之前形成一種頭尾相接的迴圈等待資源關係

    如何避免死鎖

             在系統設計程序排程等方面注意不讓這四個條件成立,確定資源的合理分配演算法,避免程序永久佔據系統資源。