并發編程模型
一.分類
按照線程通信機制可以分為共享內存模型和消息傳遞模型:
1.共享內存模型:線程之間共享程序的公共狀態,編程之間通過讀寫內存中的公共狀態來隱式進行通信。相互通信的進程共享某些數據結構或共享存儲區,進程通過這些空間進行通信,因此又可以分為兩種類型:
1).基于共享數據結構的通信方式。在這種通信方式中要求各進程公用某些數據結構來實現進程間的信息交換。比如用有界緩沖區這種數據結構實現生產者-消費者問題。在這里公用數據結構的設置和進程間同步的處理,會增加負擔,所以這種通信方式是低微的,只適用于傳遞相對少量的數據。
2).基于共享存儲區的通信方式。為了大量傳輸數據,在存儲器中劃分出了一塊共享存儲區;各個進程可以通過對數據的讀或寫來實現通信。這種方式下,進程在通信前,先向系統申請獲得共享存儲區的一個分區并指定該分區的關鍵字;若系統已經給其他進程分配了這樣的分區,則返回該分區的描述符,申請者將獲得的共享存儲分區連接到本進程上,然后就可以像讀寫普通存儲器一樣地讀寫公共存儲分區。
2.消息傳遞模型:線程之間沒有公共狀態,線程之間必須通過明確的發送消息來顯示進行通信,當任務在不同的計算機上運行時通常使用。 當任務需要與另一個進行通信時,它會發送遵循預定義協議的消息。 如果發送方在發送消息后繼續執行,發送方被阻塞等待響應或異步,則該通信可以是同步的。消息系統的功能是允許進程與其它的進程進行通信。我們已經看到了消息傳遞在微內核中的應用。在這種方案下,服務作為普通的用戶進程提供,服務在內核之外。用戶進程之間的通信通過傳遞消息完成。IPC 至少提供了兩種操作:send和receive。 進程發送的消息可以是定長的也可以是變長的。如果只可以發送定長的消息,那么系統層的實現就很簡單。然而,這種限制增加了 程序設計的難度。另一方面,變長的消息需要更復雜的系統層實現,但是 程序設計工作更簡單
如果進程P 和Q要進行通信,那么它們必須能夠互相發送和接收消息;二者之間必須要建立一條通信鏈路。有多種方法可以實現這條鏈路。在這兒,我們并不關心鏈路的物理實現,而是要考慮它的邏輯實現。有如下幾種用于邏輯實現send/receive 操作的方法:
-
直接或間接通信
-
對稱或不對稱通信
-
自動或手動緩沖
-
發送拷貝或引用
-
定長消息或變長消息
同步是指程序用于控制不同線程之間操作發生相對順序的機制。在共享內存并發模 型里,同步是顯式進行的。程序員必須顯式指定某個方法或某段代碼需要在線程之 間互斥執行。在消息傳遞的并發模型里,由于消息的發送必須在消息的接收之前, 因此同步是隱式進行的。
實現同步的機制主要有臨界區、互斥、信號量和事件
臨界區:通過對多線程的串行化來訪問公共資源或一段代碼,速度快,適合控制數據訪問。在任意時刻只允許一個線程對共享資源進行訪問,如果有多個線程試圖訪問公共資 源,那么在有一個線程進入后,其他試圖訪問公共資源的線程將被掛起,并一直等到進入臨界區的線程離開,臨界區在被釋放后,其他線程才可以搶占。
互斥量:采用互斥對象機制。 只有擁有互斥對象的線程才有訪問公共資源的權限,因為互斥對象只有一個,所以能保證公共資源不會同時被多個線程訪問。互斥不僅能實現同一應用程序的公共資源安全共享,還能實現不同應用程序的公共資源安全共享 .互斥量比臨界區復雜。因為使用互斥不僅僅能夠在同一應用程序不同線程中實現資源的安全共享,而且可以在不同應用程序的線程之間實現對資源的安全共享。
信號量:它允許多個線程在同一時刻訪問同一資源,但是需要限制在同一時刻訪問此資源的最大線程數目 。信號量對象對線程的同步方式與前面幾種方法不同,信號允許多個線程同時使用共享資源,這與操作系統中的PV操作相同。它指出了同時訪問共享資源的線程最大數目。它允許多個線程在同一時刻訪問同一資源,但是需要限制在同一時刻訪問此資源的最大線程數目。
事件:通過通知操作的方式來保持線程的同步,還可以方便實現對多個線程的優先級比較的操作 。
注:Java 的并發采用的是共享內存模型,Java 線程之間的通信總是隱式進行,整個通 信過程對程序員完全透明。