這幾天同事在處理RK平臺的基于mipi協(xié)議的數(shù)據(jù)時候泽谨,碰到數(shù)據(jù)透傳到usb到PC端的時候出現(xiàn)問題,因為數(shù)據(jù)量比較大特漩,加上是并發(fā)傳輸吧雹,所以通信上用到了生產(chǎn)者消費者模式。
生產(chǎn)者消費者模式涂身,或者更貼切的說它是一種模型雄卷,不能說屬于一種設(shè)計模式。具體來講蛤售,就是一個系統(tǒng)中存在生產(chǎn)者和消費者兩種角色丁鹉,他們通過內(nèi)存緩沖區(qū)進(jìn)行通信,而如何保證并發(fā)通信悴能,這就是程序員要思考的問題揣钦。比如說國內(nèi)的淘寶,拼多多漠酿,京東等超級流量級別的電子商務(wù)冯凹,用戶訪問瀏覽頁面的時候,圖片資源以及網(wǎng)頁內(nèi)容要在幾秒內(nèi)就刷出來炒嘲,這些就是程序員工程師的智慧的結(jié)晶宇姚,而背后很大程度上生產(chǎn)者與消費者模式用得淋漓盡致。
生產(chǎn)者是一個或者一堆線程夫凸,消費者也是一個或者一堆堆線程浑劳,內(nèi)存緩沖區(qū)可以使用List數(shù)組隊列,數(shù)據(jù)類型只需要定義一個簡單的類寸痢,如何處理多線程之間的協(xié)作通信呀洲。這是一門藝術(shù)性的問題,像我工作中遇到的場景啼止,rk平臺的mipi數(shù)據(jù)總是不斷的吐露出來道逗,而我要能隨時接納數(shù)據(jù)并且不能影響幀率,這就很考驗人献烦。我同事遇到就懵圈了滓窍,不會利用這個模式去解決問題,如果你還在用單線程的操作去設(shè)立數(shù)據(jù)緩存區(qū)巩那,我覺得就有點愚蠢了吏夯。
在這個模型中此蜈,最關(guān)鍵就是內(nèi)存緩沖區(qū)為空的時候消費者必須等待,而內(nèi)存緩沖區(qū)滿的時候噪生,生產(chǎn)者必須等待裆赵。其他時候可以是個動態(tài)平衡。值得注意的是多線程對臨界區(qū)資源的操作時候必須保證在讀寫中只能存在一個線程跺嗽,所以需要設(shè)計鎖的策略战授。
這里要提到的是用intel線程庫tbb的使用,Intel 宣布桨嫁,Threading Building Blocks植兰,Intel 眾多軟件開發(fā)工具中的一個,open source了璃吧。協(xié)議是 GPLv2楣导。我在自己場景中是利用tbb這個庫來創(chuàng)建線程,實現(xiàn)這個生產(chǎn)者與消費者模型畜挨。
tbb創(chuàng)建生產(chǎn)者與消費者并發(fā)線程隊列
生產(chǎn)者隊列
消費者隊列
實際中應(yīng)用
當(dāng)然用tbb直接來創(chuàng)建線程隊列筒繁,你可能無法去領(lǐng)悟它的精髓,所以建議你還是不要以來tbb這個庫朦促,而自己單純的用創(chuàng)建線程的方式手撕這部分代碼膝晾。
這個模型的核心精髓是緩沖區(qū)的設(shè)立栓始。而且你可以采用隊列务冕,管道,sockert或者其他方式去設(shè)計分配這塊內(nèi)存緩沖區(qū)幻赚。當(dāng)數(shù)據(jù)制造快的時候禀忆,消費者來不及處理,未處理的數(shù)據(jù)可以暫時存在緩沖區(qū)中落恼。等生產(chǎn)者的制造速度慢下來箩退,消費者再慢慢處理掉。
當(dāng)然它支持并發(fā)的同時也帶來一個弊端佳谦。由于函數(shù)調(diào)用是同步的(或者叫阻塞的)戴涝,在消費者的方法沒有返回之前,生產(chǎn)者只好一直等在那邊钻蔑。萬一消費者處理數(shù)據(jù)很慢啥刻,生產(chǎn)者就會白白糟蹋大好時光。因為RK平臺咪笑,全志813平臺可帽,聯(lián)發(fā)科平臺這些SOC芯片處理器吐出的數(shù)據(jù)是非常快的窗怒,如果你不設(shè)立緩沖區(qū)映跟,或者不去設(shè)計這么一塊區(qū)域去處理數(shù)據(jù)蓄拣,或者基于ISP算法處理,那么你肯定會影響到幀率速度努隙,甚至于芯片的性能無法完美的詮釋球恤。
使用了生產(chǎn)者/消費者模式之后,生產(chǎn)者和消費者可以是兩個獨立的并發(fā)主體荸镊。生產(chǎn)者把制造出來的數(shù)據(jù)往緩沖區(qū)一丟碎捺,就可以再去生產(chǎn)下一個數(shù)據(jù)〈蓿基本上不用依賴消費者的處理速度收厨。這個模式是不在GOF提出的23種設(shè)計模式之中的,它不是基于面向?qū)ο蟮脑O(shè)計模式优构,而是面向過程的一個設(shè)計模式诵叁,所以經(jīng)常被廣泛用于系統(tǒng)性的架構(gòu)當(dāng)中。