執行緒通訊機制:共享記憶體 VS 訊息傳遞

五柳-先生發表於2015-05-30

執行緒通訊機制:共享記憶體 VS 訊息傳遞


在併發程式設計中,我們必須考慮的問題時如何在兩個執行緒間進行通訊。這裡的通訊指的是不同的執行緒之間如何交換資訊


目前有兩種方式:

1、共享記憶體

2、訊息傳遞(actor 模型)


共享記憶體

共享記憶體這種方式比較常見,我們經常會設定一個共享變數。然後多個執行緒去操作同一個共享變數。從而達到執行緒通訊的目的。例如,我們使用多個執行緒去執行頁面抓取任務,我們可以使用一個共享變數count來記錄任務完成的數量。每當一個執行緒完成抓取任務,會在原來的count上執行加1操作。這樣每個執行緒都可以通過獲取這個count變數來獲得當前任務的完成情況。當然必須要考慮的是共享變數的同步問題,這也共享記憶體容易出錯的原因所在。

這種通訊模型中,不同的執行緒之間是沒有直接聯絡的。都是通過共享變數這個“中間人”來進行互動。而這個“中間人”必要情況下還需被保護在臨界區內(加鎖或同步)。由此可見,一旦共享變數變得多起來,並且涉及到多種不同執行緒物件的互動,這種管理會變得非常複雜,極容易出現死鎖等問題。


訊息傳遞

訊息傳遞方式採取的是執行緒之間的直接通訊,不同的執行緒之間通過顯式的傳送訊息來達到互動目的。訊息傳遞最有名的方式應該是actor模型了。在這種模型下,一切都是actor,所有的actor之間的通訊都必須通過傳遞訊息才能達到。每個actor都有一個收件箱(訊息佇列)用來儲存收到其他actor傳遞來的訊息。actor自己也可以給自己傳送訊息。這才是物件導向的精髓啊!

這種模型看起來比共享記憶體模型要複雜。但是一旦碰到複雜業務的話,actor模型的優勢就體現出來了。我們還是以剛才多執行緒抓取網站為例子看一下在這種模型下如何去解決。


首先我們定義一個統計actor用來統計任務完成量。然後把多個網址(訊息方式)發給多個抓取actor,抓取actor處理完任務後傳送訊息通知統計actor任務完成,統計actor對自己儲存的變數count(這個只有統計actor才能看到)加一。


最後讓我們來總結一下這兩種通訊模式:

併發模型 通訊機制 同步機制
共享記憶體

執行緒之間共享程式的公共狀態,執行緒之間通過寫-讀記憶體中的公共狀態來隱式進行通訊。

同步是顯式進行的。程式設計師必須顯式指定某個方法或某段程式碼需要線上程之間互斥執行。

訊息傳遞(actor)

執行緒之間沒有公共狀態,執行緒之間必須通過明確的傳送訊息來顯式進行通訊。


相關文章