◇判斷「空」和「滿」java
上述的操做並不複雜,不過有一個小小的麻煩:空環和滿環的時候,R和W都指向同一個位置!這樣就沒法判斷究竟是「空」仍是「滿」。大致上有兩種方法能夠解決該問題。程序員
辦法1:始終保持一個元素不用編程
當空環的時候,R和W重疊。當W比R跑得快,追到距離R還有一個元素間隔的時候,就認爲環已經滿。當環內元素佔用的存儲空間較大的時候,這種辦法顯得很土(浪費空間)。數組
辦法2:維護額外變量安全
若是不喜歡上述辦法,還能夠採用額外的變量來解決。好比能夠用一個整數記錄當前環中已經保存的元素個數(該整數>=0)。當R和W重疊的時候,經過該變量就能夠知道是「空」仍是「滿」。架構
◇元素的存儲併發
因爲環形緩衝區自己就是要下降存儲空間分配的開銷,所以緩衝區中元素的類型要選好。儘可能存儲值類型的數據,而不要存儲指針(引用)類型的數據。由於指針類型的數據又會引發存儲空間(好比堆內存)的分配和釋放,使得環形緩衝區的效果打折扣。編程語言
★應用場合性能
剛纔介紹了環形緩衝區內部的實現機制。按照前一個帖子的慣例,咱們來介紹一下在線程和進程方式下的使用。spa
若是你所使用的編程語言和開發庫中帶有現成的、成熟的環形緩衝區,強烈建議使用現成的庫,不要從新制造輪子;確實找不到現成的,才考慮本身實現。若是你純粹是業餘時間練練手,那另當別論。
◇用於併發線程
和線程中的隊列緩衝區相似,線程中的環形緩衝區也要考慮線程安全的問題。除非你使用的環形緩衝區的庫已經幫你實現了線程安全,不然你仍是得本身動手搞定。線程方式下的環形緩衝區用得比較多,相關的網上資料也多,下面就大體介紹幾個。
對於C++的程序員,強烈推薦使用boost提供的circular_buffer模板,該模板最開始是在boost 1.35版本中引入的。鑑於boost在C++社區中的地位,大夥兒應該能夠放心使用該模板。
對於C程序員,能夠去看看開源項目circbuf,不過該項目是GPL協議的,不太爽;並且活躍度不過高;並且只有一個開發人員。大夥兒慎用!建議只拿它當參考。
對於C#程序員,能夠參考CodeProject上的一個示例。
◇用於併發進程
進程間的環形緩衝區,彷佛少有現成的庫可用。大夥兒只好本身動手、豐衣足食了。
適用於進程間環形緩衝的IPC類型,常見的有共享內存和文件。在這兩種方式上進行環形緩衝,一般都採用數組的方式實現。程序事先分配好一個固定長度的存儲空間,而後具體的讀寫操做、判斷「空」和「滿」、元素存儲等細節就可參照前面所說的來進行。
共享內存方式的性能很好,適用於數據流量很大的場景。可是有些語言(好比Java)對於共享內存不支持。所以,該方式在多語言協同開發的系統中,會有必定的侷限性。
而文件方式在編程語言方面支持很好,幾乎全部編程語言都支持操做文件。但它可能會受限於磁盤讀寫(Disk I/O)的性能。因此文件方式不太適合於快速數據傳輸;可是對於某些「數據單元」很大的場合,文件方式是值得考慮的。
對於進程間的環形緩衝區,一樣要考慮好進程間的同步、互斥等問題,限於篇幅,此處就不細說了。