架構設計:生產者/消費者模式 第5頁:環形緩衝區

[3]:環形緩衝區 數組

    前一個帖子說起了隊列緩衝區可能存在的性能問題及解決方法:環形緩衝區。今天就專門來描述一下這個話題。 性能

    爲了防止有人給咱扣上「過分設計」的大帽子,事先聲明一下:只有當存儲空間的分配/釋放很是頻繁而且確實產生了明顯的影響,你才應該考慮環形緩衝區的使 用。不然的話,仍是老老實實用最基本、最簡單的隊列緩衝區吧。還有一點須要說明一下:本文所說起的「存儲空間」,不只包括內存,還可能包括諸如硬盤之類的 存儲介質。 設計

    ★環形緩衝區 vs 隊列緩衝區 索引

    ◇外部接口類似 接口

    在介紹環形緩衝區以前,我們先來回顧一下普通的隊列。普通的隊列有一個寫入端和一個讀出端。隊列爲空的時候,讀出端沒法讀取數據;當隊列滿(達到最大尺寸)時,寫入端沒法寫入數據。 隊列

    對於使用者來說,環形緩衝區和隊列緩衝區是同樣的。它也有一個寫入端(用於push)和一個讀出端(用於pop),也有緩衝區「滿」和「空」的狀態。因此,從隊列緩衝區切換到環形緩衝區,對於使用者來講能比較平滑地過渡。 進程

    ◇內部結構迥異 內存

    雖然二者的對外接口差很少,可是內部結構和運做機制有很大差異。隊列的內部結構此處就很少囉嗦了。重點介紹一下環形緩衝區的內部結構。 遍歷

    大夥兒能夠把環形緩衝區的讀出端(如下簡稱R)和寫入端(如下簡稱W)想象成是兩我的在體育場跑道上追逐(R追W)。當R追上W的時候,就是緩衝區爲空;當W追上R的時候(W比R多跑一圈),就是緩衝區滿。 方法

    爲了形象起見,去找來一張圖並略做修改,以下:

    從上圖能夠看出,環形緩衝區全部的push和pop操做都是在一個固定的存儲空間內進行。而隊列緩衝區在push的時候,可能會分配存儲空間用於存儲新元 素;在pop時,可能會釋放廢棄元素的存儲空間。因此環形方式相比隊列方式,少掉了對於緩衝區元素所用存儲空間的分配、釋放。這是環形緩衝區的一個主要優 勢。

    ★環形緩衝區的實現

    若是你手頭已經有現成的環形緩衝區可供使用,而且你對環形緩衝區的內部實現不感興趣,能夠跳過這段。

    ◇數組方式 vs 鏈表方式

    環形緩衝區的內部實現,便可基於數組(此處的數組,泛指連續存儲空間)實現,也可基於鏈表實現。

    數組在物理存儲上是一維的連續線性結構,能夠在初始化時,把存儲空間一次性分配好,這是數組方式的優勢。可是要使用數組來模擬環,你必須在邏輯上把數組的 頭和尾相連。在順序遍歷數組時,對尾部元素(最後一個元素)要做一下特殊處理。訪問尾部元素的下一個元素時,要從新回到頭部元素(第0個元素)。以下圖所 示:

    使用鏈表的方式,正好和數組相反:鏈表省去了頭尾相連的特殊處理。可是鏈表在初始化的時候比較繁瑣,並且在有些場合(好比後面提到的跨進程的IPC)不太方便使用。

    ◇讀寫操做

    環形緩衝區要維護兩個索引,分別對應寫入端(W)和讀取端(R)。寫入(push)的時候,先確保環沒滿,而後把數據複製到W所對應的元素,最後W指向下一個元素;讀取(pop)的時候,先確保環沒空,而後返回R對應的元素,最後R指向下一個元素。

相關文章
相關標籤/搜索